仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

Kubernetes Podアプリに外部HAProxyでVIPアクセスする

今回はKubernetesのPodでWebサービスを起動した時に、外部HAProxyを使ってVIPでアクセスする方法をまとめたいと思います。 前提条件は次の通りです。

  • JujuとMAASで構築したKubernetesを想定
  • nodePortを固定してPodを作成している
  • 外部HAProxyサーバーは固定のIPアドレスを設定している
  • Kubernetes環境とHAProxyサーバーはIPレベルで通信が可能であること

HAProxyサーバーの準備

まず、HAProxyサーバーの準備からです。今回はDebianを使いましたが、Ubuntuでも基本的には一緒です。

% sudo apt update && sudo apt install haproxy

Kernelのbind設定を変更します。

% sudo vi /etc/sysctl.conf
...
net.ipv4.ip_nonlocal_bind = 1    #最終行に追記

HAProxyを有効にします。

% sudo vi /etc/default/haproxy
...
ENABLED=1    #最終行に追記

HAProxyの設定をします。フロントエンドはHAProxyサーバー側の受け口の設定で、バックエンドはKubernetes workerのホストを指定します。 Kubernetes workerのホストのIPアドレスをjuju statusコマンドやMAAS Dashboardなどで確認します。

% sudo vi /etc/haproxy/haproxy.cfg
...
# フロントエンドを定義 ( http-in の箇所は任意の名前 )                                                                              
frontend http-in
  bind *:30080
  # デフォルトのバックエンドを定義                                                                                                 
  default_backend    backend_servers
  # X-Forwarded-For ヘッダーを渡す                                                                                                 
  option             forwardfor

# バックエンドを定義                                                                                                               
backend backend_servers
  # ラウンドロビンで負荷分散                                                                                                       
  balance            roundrobin
  # バックエンドサーバーを定義                                                                                                     
  server             www1 172.17.28.53:30080 check
  server             www2 172.17.28.54:30080 check

設定を反映するために、次のようにコマンドを実行します。

% sudo sysctl -p
% sudo systemctl restart haproxy

Podを作成

次にPodを作成して、PodでNginxアプリケーションを実行します。

まずはノードを確認します。2台のKubernetes Workerがあることがわかります。

% kubectl get no
NAME           STATUS    ROLES     AGE       VERSION
cuddly-tapir   Ready     <none>    5d        v1.10.6
solid-llama    Ready     <none>    5d        v1.10.6

アプリケーションをデプロイするため、次のようなYAMLファイルを作成します。 Workerが2台あるのでreplicas: 2を指定します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginxapp1
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginxapp1
    spec:
      containers:
      - name: nginxapp1
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginxapp1-nodeport
  labels:
    app: nginxapp1
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: nginxapp1

コンテナーではNginxを80ポートで待ち受けします。そのコンテナーに対して、nodePortとして固定の30080ポートをサービスとして割り当てます。

前のステップで作成したYAMLを使ってPodを作成します。次のコマンドを実行します。

% kubernetes create -f nginx-deployset.yml

kubectl getして、AVAILABLEが2になったことを確認します。次のコマンドを実行します。

% kubectl get -f nginx-deployset.yml 
NAME                              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/nginxapp1   2         2         2            2           38m

NAME                         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/nginxapp1-nodeport   NodePort   10.152.183.126   <none>        80:30080/TCP   38m

nginxapp1がどのノードに展開されたか確認します。次のコマンドを実行します。

% kubectl get po -o wide|grep nginxapp1
nginxapp1-5999d5db77-bv6fh                         1/1       Running   0          42m       10.1.78.43     cuddly-tapir
nginxapp1-5999d5db77-z77rc                         1/1       Running   0          42m       10.1.46.31     solid-llama
(cuddly-tapirとsolid-llamaというホストに展開されたことがわかる)

以上で、準備が整いました。curlコマンドやブラウザーでそれぞれのホストでnodePortでアクセスしたり、HAProxyでアクセスしてみましょう。同じ内容が表示されるはずです。

% curl http://172.17.28.53:30080
% curl http://172.17.28.54:30080
(NginxがそれぞれのnodePortでアクセスできることを確認)

% curl http://172.17.28.6:30080
(HAProxyのIPアドレス経由でアクセスできることを確認)

結果出力例

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

参考にしたサイト