昨日のKubernetes 1.12インストールに引き続き、今回はそのKubernetesにIngress Controllerを導入しよう。ワーカーノード2台あるので、そいつの上にDaemonSetで。
keepalivedでHA化もしよう。
#NGINX Ingress Controllerを導入
どうもなかなかBetaが取れないIngress Controller。まあ、LoadBalancerのServiceですべてが賄えるならいらん訳だけど、Kubernetes成熟しないなあと思う一因でもある。それはとりあえず、Nginx Ingressのインストールの手順は以下。インストール手順探すのも現状ちょい手間。
https://kubernetes.github.io/ingress-nginx/deploy/
Mandatory commandでkubectl apply直接実行してもいいのだけど、今回はDaemonSetでデプロイしたいのでいったんダウンロードして加工。またhostPort 80, 443を割り当て。
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml>mandatory.yaml
vi mandatory.yaml
■"name: nginx-ingress-controller"であるDeploymentをDaemonSetに書き換え
(変更前)
251 apiVersion: extensions/v1beta1
252 kind: Deployment
253 metadata:
254 name: nginx-ingress-controller
(変更後)
251 apiVersion: extensions/v1beta1
252 kind: DaemonSet
253 metadata:
254 name: nginx-ingress-controller
---
■ReplicaSetでなくなるのでreplica行を削除
(変更前)
259 spec:
260 replicas: 1
(変更後)
259 spec:
260 # replicas: 1
---
■hostPortを追加
(変更前)
303 ports:
304 - name: http
305 containerPort: 80
306 - name: https
307 containerPort: 443
(変更後)
303 ports:
304 - name: http
305 containerPort: 80
306 hostPort: 80
307 - name: https
308 containerPort: 443
309 hostPort: 443
---
kubectl create -f mandatory.yaml
ingress-nginxネームスペースにIngress Controllerがデプロイされる。
# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
default-http-backend-6d6985d9d4-hv9dk 1/1 Running 0 81s
nginx-ingress-controller-j6fjn 1/1 Running 0 81s
nginx-ingress-controller-pjxkc 1/1 Running 0 81s
root@m16:~#
#keepalivedを導入
せっかく2台のノードに1つずつIngress Controllerがいるので、keepalivedを使って2ノードのHAを構成したい。
まずは1台目のノードで以下を実行。
apt-get -y install ipvsadm keepalived
その1台目用の設定ファイルを作る。
vrrp_instance INGRESS {
state MASTER
interface ens32
virtual_router_id 50
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.134/24
}
}
※vipのサブネット指定(/24)必要だったっけと思ったが、指定しないと同じ筐体内のVMとVIPで通信できなくなる問題があったため、ここでは指定。
keepalivedを起動。
systemctl start keepalived
続いて2台目のノードで以下を実行。
apt-get -y install ipvsadm keepalived
その2台目用の設定ファイルを作る。
vrrp_instance INGRESS {
state MASTER
interface ens32
virtual_router_id 50
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.134/24
}
}
keepalivedを起動。
systemctl start keepalived
#動作確認
せっかくなので先日作ったNode.js->Mariadbのサンプルアプリをデプロイし、Ingressリソースを作って動作確認。
記事中にある「# REG=<レジストリ:ポート番号/namespace>」のところは、DockerHub上にレポジトリを作ったので「# REG=docker.io/rk05231977」で。
また、最後の「# PROXYIP=<kube-proxyが動作するサーバのIPアドレス>」は、今回の環境ではVIPの「# PROXYIP=192.168.0.134」。
そしてIngressリソースを作成。以下のファイルを作り、
kind: Ingress
metadata:
name: my-node-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: my-node
servicePort: 80
host: my-node.com
以下のコマンドでデプロイ。
kubectl create -f my-node-ingress.yaml
Ingressリソースが出来ているか確認。
# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
my-node-ingress my-node.com 80 2m17s
# kubectl exec -n ingress-nginx nginx-ingress-controller-j6fjn -- grep -2 "my-node.com" /etc/nginx/nginx.conf
## end server _
## start server my-node.com
server {
server_name my-node.com ;
listen 80;
--
}
## end server my-node.com
# default server, used for NGINX healthcheck and access to nginx stats
うん、良さそう。
以下のcurlコマンドで、VIP(今回の環境では192.168.0.134)に向けて「Host: my-node.com」ヘッダを付けて接続確認。
# curl -H "Host: my-node.com" 192.168.0.134
<html><body>
date: Sat Sep 29 2018 09:56:27 GMT+0000 (Coordinated Universal Time)<br/>
hostname: my-node-54d74b647-czsw5<br/>
remoteAddress: ::ffff:10.0.2.15<br/>
db:record: Success!<br/>
</html></body>
一応、1台ずつノードを停止して、まあ、Ingressは動作してVIPが引き継がれることも確認。
いくつか問題はあり、一つ目は、サンプル用アプリのDBがコンテナ再起動時にデータベースがなくなってしまうのでmariadb Podができるたびにcat > my-db.sql << 'EOF'
~のコマンド実行してDB作り直さなければいけないということと、2つ目はVIPフェールオーバー時は問題ないのだけど、その後プライマリノードが起動してくるときにIngress Controllerより先にkeepalivedが起動してしまうので一時的にアプリに接続不可になる。
後者についてはkeepalivedを自動起動しないとか、起動まで30秒ぐらいdelayを掛けなければいけない。
(変更前)
8 [Service]
9 Type=forking
(変更後)
8 [Service]
9 ExecStartPre=/bin/sleep 30
10 Type=forking
systemctl daemon-reload