Consul をKubernetes にインストールする

 自分備忘録用メモ。Kubernetes 環境にConsul をデプロイした際の手順です。


前提条件

Consul はEnterprise 版を利用しています。

手順

 

Kubernetes の準備

Consul をインストールするためのKubernetes 環境を準備しておきます。この後インストールするConsul UI に関しては、Contour のIngress 経由でアクセスする様に設定していきます。環境が違いますが、こちらの「Tanzu Kubernetes Grid(TKGm) v1.3.1 にContour, Harbor, TBS をデプロイした際の手順」が参考になります。
Ingress コントローラーのContour の導入、Let's Encrypt での証明書の取得までを実施しておきます。
 
また、上の手順で利用しているvSphere 環境におけるTKG ですが、VMUG Advantage を購入すると、利用出来るTanzu Basic で利用可能です。VMUG Advantage は、$200/Year 必要ですが、3年で購入すると割引が効くので、個人的には3年で利用するのがオススメです。

Consul Enterprise インストール前準備

Consul をインストールするKubernetes でConsul UI 用のTLS Secrets を作成します。今回、Consul はNamespace:consul にデプロイしていますので、事前にNamespace を作成しています。
k create ns consul
k -n consul create secret tls consul-tls-secret \
  --cert=./lab-cert/<CLUSTER_NAME>/cfg/live/<CLUSTER_NAME>.<MYDOMAIN>/fullchain.pem \
  --key=./lab-cert/<CLUSTER_NAME>/cfg/live/<CLUSTER_NAME>.<MYDOMAIN>/privkey.pem
 
Consul Server Agent / Client Agent 間で利用するための証明書を作成します。こちらの「Secure Consul Agent Communication with TLS Encryption」を参考に証明書を作成します。※以下のコマンドを実施するために、事前にConsul のバイナリはインストールしておいて下さい
$ consul tls ca create
==> Saved consul-agent-ca.pem
==> Saved consul-agent-ca-key.pem
$ consul tls cert create -server -dc dc1
...
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-server-consul-0.pem
==> Saved dc1-server-consul-0-key.pem
 
証明書を作成したら、 後ほどhelm のvaules.yml で利用するため、上記ファイルを元にSecret を作成しておきます。
k -n consul create secret generic consul-ca-cert \
    --from-file='tls.crt=./consul-agent-ca.pem'
k -n consul create secret generic consul-ca-key \
    --from-file='tls.key=./consul-agent-ca-key.pem'
 
この後、Consul の設定ファイルで指定するための、Secret を作成しておきます。こちらの「Add an Enterprise license key (optional)」と「Add a gossip encryption key (optional)」を実施しておきます。
Consul Enterprise の30日間のトライアルライセンスはこちらから申請する事で利用する事が可能です。--from-literal=key= で指定するのは、ライセンスファイルに記載されている文字列全てです。
k -n consul create secret generic consul-license --from-literal=key=<LICENSE_FILE>
k -n consul create secret generic consul-gossip-encryption-key --from-literal=key=$(consul keygen)

今回は、Contour をIngress コントローラーとして利用しますが、Consul UI 利用時の注意点として、"Please ensure the Ingress Controller supports SSL pass-through and it is enabled to ensure traffic forwarded to port 443 has not been TLS terminated." と記載がありますので、Contour のTLS Pass through 設定をしておきます。
$ cat << EOF > httpproxy-tls-passthrough.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: consul
  namespace: consul
spec:
  virtualhost:
    fqdn: consul.<CLUSTER_NAME>.<MY_DOMAIN>
    tls:
      passthrough: true
  tcpproxy:
    services:
    - name: consul-ui
      port: 443
k -n consul apply -f httpproxy-tls-passthrough.yaml
$ k -n consul get httpproxies.projectcontour.io
NAME     FQDN                           TLS SECRET   STATUS   STATUS DESCRIPTION
consul   consul.<CLUSTER_NAME>.<MY_DOMAIN>                valid    Valid HTTPProxy
 
以上の準備が出来たら、以下のような形でConsul をhelm でインストールための、values ファイルを作成します。consul-k8s は最新版を選択する方が良いと思います。一つ前のバージョンですと、webhook-cert-manager Pod がちゃんと立ち上がりませんでした。。。
$ cat << EOF > values.yml
global:
  enabled: true
  name: consul
  image: "hashicorp/consul-enterprise:1.10.1-ent"
  imageK8S: "hashicorp/consul-k8s:0.26.0"
  datacenter: dc1
  acls:
    manageSystemACLs: true
  metrics:
    enabled: true
  gossipEncryption:
    secretName: 'consul-gossip-encryption-key'
    secretKey: 'key'
  tls:
    enabled: true
    enableAutoEncrypt: true
    caCert:
      secretName: consul-ca-cert
      secretKey: tls.crt
    caKey:
      secretName: consul-ca-key
      secretKey: tls.key
server:
  replicas: 1
  enterpriseLicense:
    secretName: 'consul-license'
    secretKey: 'key'
client:
  enabled: true
ui:
  enabled: true
  ingress:
    enabled: true
    hosts:
      - host: consul.<CLUSTER_NAME>.<MY_DOMAIN>
    tls:
      - hosts:
        - consul.<CLUSTER_NAME>.<MY_DOMAIN>
        secretName: consul-tls-secret
    annotations: |
      ingress.kubernetes.io/force-ssl-redirect: "true"     # force https, even if http is requested
      kubernetes.io/ingress.class: contour                 # using Contour for ingress
      kubernetes.io/tls-acme: "true"                       # using ACME certificates for TLS
      projectcontour.io/upstream-protocol.tls: "443"
   metrics:
    enabled: true
    provider: prometheus
    baseURL: http://prometheus-server
connectInject:
  enabled: true
  default: true
controller:
  enabled: true
prometheus:
  enabled: true
EOF

Consul Enterprise インストール

helm を利用して、consul をインストールします。
helm repo update
helm repo add hashicorp https://helm.releases.hashicorp.com
helm upgrade --install consul hashicorp/consul -f values.yml --namespace consul
 
リソースが稼働している事を確認します。
$ k -n consul get all
NAME                                                              READY   STATUS    RESTARTS   AGE
pod/consul-connect-injector-webhook-deployment-848945984b-fsdz5   1/1     Running   0          34h
pod/consul-connect-injector-webhook-deployment-848945984b-gv6k5   1/1     Running   0          34h
pod/consul-controller-65fdc48bcf-w48lf                            1/1     Running   0          34h
pod/consul-dznnd                                                  1/1     Running   0          34h
pod/consul-server-0                                               1/1     Running   0          34h
pod/consul-webhook-cert-manager-56cdbb7648-s8ckd                  1/1     Running   0          34h
pod/consul-z4t9t                                                  1/1     Running   0          34h
pod/prometheus-server-c5f9465d-trc6w                              2/2     Running   0          32s

NAME                                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                   AGE
service/consul-connect-injector-svc   ClusterIP   100.70.77.185    <none>        443/TCP                                                                   34h
service/consul-controller-webhook     ClusterIP   100.66.47.29     <none>        443/TCP                                                                   34h
service/consul-dns                    ClusterIP   100.70.217.227   <none>        53/TCP,53/UDP                                                             34h
service/consul-server                 ClusterIP   None             <none>        8501/TCP,8301/TCP,8301/UDP,8302/TCP,8302/UDP,8300/TCP,8600/TCP,8600/UDP   34h
service/consul-ui                     ClusterIP   100.69.22.51     <none>        443/TCP                                                                   34h
service/prometheus-server             ClusterIP   100.71.179.72    <none>        80/TCP                                                                    32s

NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/consul   2         2         2       2            2           <none>          34h

NAME                                                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/consul-connect-injector-webhook-deployment   2/2     2            2           34h
deployment.apps/consul-controller                            1/1     1            1           34h
deployment.apps/consul-webhook-cert-manager                  1/1     1            1           34h
deployment.apps/prometheus-server                            1/1     1            1           32s

NAME                                                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/consul-connect-injector-webhook-deployment-848945984b   2         2         2       34h
replicaset.apps/consul-controller-65fdc48bcf                            1         1         1       34h
replicaset.apps/consul-webhook-cert-manager-56cdbb7648                  1         1         1       34h
replicaset.apps/prometheus-server-c5f9465d                              1         1         1       32s

NAME                             READY   AGE
statefulset.apps/consul-server   1/1     34h
 
Consul UI を利用してアクセスしてみるとClient sent an HTTP request to an HTTPS server.  とメッセージが出力されました。annotation で指定したものの、どうもContour 側でTLS Termination されてしまっているようです。
consul-ui サービスのannotation を修正して、再度アクセスしてみます。
$ k -n consul get svc consul-ui -oyaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: consul
    meta.helm.sh/release-namespace: consul
    projectcontour.io/upstream-protocol.tls: "443" # <- Add
...

consul.<CLUSTER_NAME>.<MYDOMAIN> にブラウザでアクセスしてみると、無事にConsul UI にアクセスする事が出来ました。

ACL を設定しているので、トークンを取得し、Consul UI にログインします。トークンは以下のコマンドで取得出来ます。
k -n consul get secrets/consul-bootstrap-acl-token --template={{.data.token}} | base64 --decode

Consul UI 右上のLogin をクリックし、上のコマンドで取得したトークンを入力します。

ログイン出来るとConsul UI が以下の様な形の表示に変わり、先程よりも表示されている内容が増えていると思います。

Consul のHTTP API を操作するには、以下のコマンドで直接consul-server Pod にログインして操作する事も出来ます。
k -n consul exec -it pod/consul-server-0 -- /bin/sh
$ consul -version
Consul v1.10.1+ent
Revision bd7294938
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

もしくは、環境変数を設定した上で、consul CLI を実行する事で可能になります。
export CONSUL_HTTP_ADDR="https://consul.<CLUSTER_NAME>.<MYDOMAIN>"
export CONSUL_HTTP_TOKEN="<TOKEN>"
$ consul services register -name=web -address=10.0.0.10 -port=8080
Registered service: web

参考

このブログの人気の投稿

Tanzu Mission Control(TMC) の NetworkPolicy を試してみる