The hard wayしたKubernetesにArgoCDを入れる

先日書いた

h3poteto.hatenablog.com

クラスタにArgoCDを入れるところまでやった.

PC起動時にvagrant upさせる

KubernetesクラスタvagrantVM内なので,物理マシンを起動した際にvagrant upしないと起動しない.これのためにいちいちsshするのは面倒なので,自動起動するようにしておく.

#!/bin/bash

cd /home/h3poteto/vagrant/kubernetes-the-hard-way-vagrant
vagrant up master

sleep 120
vagrant up node-0
vagrant up node-1

master起動後に120秒のsleepを入れているのは,masterのコンポーネント起動を待たせるため.masterが起動して,API Server, Scheduler, Controller Managerの起動が終わってからnodeを起動したい. 最初,すべてをいっぺんに起動していたのだが,masterの準備が整わないうちにnodeを起動させても,nodeはNotReadyのままエラーになってしまう.というわけでsleepさせて少し待たせている.

CURRENT_PATH=$(pwd)

cat <<EOF | sudo tee /etc/systemd/system/vagrant-up.service
[Unit]
Description=vagrant up
After=network.target
ConditionPathExists=${CURRENT_PATH}
[Service]
User=h3poteto
Group=h3poteto
Type=forking
ExecStart=${CURRENT_PATH}/vagrant-up.sh
Restart=no
TimeoutSec=15min
[Install]
WantedBy=multi-user.target
EOF

このスクリプトをsystemdで起動できるようにする.

$ sudo systemctl enable vagrant-up

とかやる必要がある.

また,このvagrant-up.sh自体はvagrantの起動後に正常終了してしまう.Type=forkingにしているのは,そのためで,ここをType=simpleとかにしてしまうと,vagrant-up.sh終了後に起動したvagrantVM自体も殺されてしまうので注意.

TimeoutSecは,前述の待ち時間とvagrantの各VMの起動時間を測って,適当に決め打ちした.

これで,物理マシンを起動ししばらく待っているとKubernetesクラスタまで勝手に起動するようになる.

ArgoCDの構成を決める

  • LAN内からしかアクセスしないので証明書は諦める
  • ingress-nginxを使ってIngressを立てる

本当は証明書をちゃんと用意したほうがいいんだけど,そもそもLAN内アクセスだと,CertManagerを使ったとしてもLet's Encryptのチャレンジをどうしたらいいか問題が残る. http-01であれば何かしらの方法で外部からサーバにアクセスできる必要はあるし,dns-01だとするとドメインを取得してそれをどこかのDNSに登録しないといけない.そしてそのドメインでArgoCDにアクセスするということは,DNSからサーバに何かしらの方法で疎通できないといけない. いずれにしろLAN内だけで公開というわけにはいかなくなる.なので諦めている.

ingress-nginxを入れる

helmfile.yaml にこんなのを書く.

releases:
  - name: nginx-ingress
    namespace: ingress-nginx
    chart: ingress-nginx/ingress-nginx
    version: 2.11.3
    values:
      - rbac:
          create: true
      - controller:
          publishService:
            enabled: true
          # https://github.com/kubernetes/ingress-nginx/issues/5401
          # https://stackoverflow.com/questions/61365202/nginx-ingress-service-ingress-nginx-controller-admission-not-found
          admissionWebhooks:
            enabled: false
          service:
            type: NodePort
            externalTrafficPolicy: Cluster
            targetPorts:
              http: http
              https: https

VagrantVMにpublic networkを設定していないので,MetalLBとかを使ってIPを割り振ってもらっても,LAN内の別PCからじゃアクセスできない. というわけで,Vagrant側でport forwardをする前提でNodePortを使っている.

admissionWebhooks を無効化しているのは,エラーが発生してしまったから.ArgoCDを入れた時点で,

FAILED RELEASES:
NAME
argocd
in ./helmfile.yaml: failed processing release argocd: command "/usr/bin/helm" exited with non-zero status:
PATH:
  /usr/bin/helm
ARGS:
  0: helm (4 bytes)
  1: upgrade (7 bytes)
  2: --install (9 bytes)
  3: --reset-values (14 bytes)
  4: argocd (6 bytes)
  5: argo/argo-cd (12 bytes)
  6: --version (9 bytes)
  7: 2.6.0 (5 bytes)
  8: --create-namespace (18 bytes)
  9: --namespace (11 bytes)
  10: argo (4 bytes)
  11: --values (8 bytes)
  12: /tmp/values726728052 (20 bytes)
  13: --values (8 bytes)
  14: /tmp/values334611523 (20 bytes)
  15: --history-max (13 bytes)
  16: 10 (2 bytes)
ERROR:
  exit status 1
EXIT STATUS
  1
STDERR:
  Error: Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": Post https://nginx-ingress-ingress-nginx-controller-admission.ingress-nginx.svc:443/extensions/v1beta1/ingresses?timeout=30s: context deadline exceeded
COMBINED OUTPUT:
  Release "argocd" does not exist. Installing it now.
  Error: Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": Post https://nginx-ingress-ingress-nginx-controller-admission.ingress-nginx.svc:443/extensions/v1beta1/ingresses?timeout=30s: context deadline exceeded

というようなエラーが発生した.

これは既にIssue化されているが,

Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io" · Issue #5401 · kubernetes/ingress-nginx · GitHub

https://github.com/kubernetes/ingress-nginx/issues/5401#issuecomment-662424306

このコメントにあるように,

stackoverflow.com

AdmissionWebhooksを無効化することで回避はできる.

ただこれ,現状無効化していいものかちょっと怪しい. そもそも古いchartではこの項目は無効化されており,以前は俺もWebhookを入れて使ったことがなかったように思う.

charts/stable/nginx-ingress at master · helm/charts · GitHub

これはchartがhelm/chartsからingress-nginxに移ったあとに有効化されたものだろう.

それ以上のことが今の段階ではわからない.とりあえずIssueがcloseされてしまっているが,同じ状態の人は多いように見える.

ArgoCDを入れる

同じくhelmfile.yaml を使う.

releases:
  - name: argocd
    namespace: argo
    chart: argo/argo-cd
    version: 2.6.0
    values:
      - installCRDs: false
      - server:
          extraArgs:
            - --insecure
          ingress:
            enabled: true
            hosts:
              - argocd.h3poteto.dev.local
            annotations:
              kubernetes.io/ingress.class: nginx

証明書を無視させたいので, --insecure を指定する.ingress側には証明書の情報は入れてない.

これでingressが作成され,

NAME            CLASS    HOSTS                       ADDRESS      PORTS   AGE
argocd-server   <none>   argocd.h3poteto.dev.local   10.32.0.72   80      11d

NodePortのingress-nginxのserviceが作られている.

NAME                                     TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-ingress-nginx-controller   NodePort   10.32.0.72   <none>        80:30768/TCP,443:31396/TCP   11d

あとは,クラスタ内のどこかのノードの30768 or 31396ポートにアクセスできれば良い.

port forwardingの設定

NodePortを使う限り,全ノードのポートに設定する必要はない.むしろどれか一つのマシンで十分だ.

  config.vm.define "node-0" do |c|
    c.vm.hostname = "node-0"

    c.vm.network "private_network", ip: "10.240.0.20"

    c.vm.network :forwarded_port, guest: 30768, host: 30768
  end

もし,NodePortで使うポートをすべて開放しておくのであれば

  config.vm.define "node-0" do |c|
    c.vm.hostname = "node-0"

    c.vm.network "private_network", ip: "10.240.0.20"

    for i in 30000..32767
      c.vm.network :forwarded_port, guest: i, host: i
    end
  end

とすれば良い.

ArgoCDにアクセス

ここまでくればVMのホストマシンの31396にアクセスすれば,ArgoCDにつながる.ただし,ドメイン名は argocd.h3poteto.dev.local にしてしまったので,このドメインでアクセスできるように,/etc/hosts

192.168.0.7 argocd.h3poteto.dev.local

とか書いておく.

あとは,

$ argocd login argocd.h3poteto.dev.local:30768 --grpc-web

とすれば良い.

ブラウザからもargocd.h3poteto.dev.local:30768 でつながる.

もしhttpsでつなぐ場合は31396だが,この場合はもちろん証明書の警告が表示される.

まとめ

VMをprivate networkのみにしてしまったので,このような形でポートフォワードしないと繋がらなくなってしまっている.本当であればpublic networkにして,IPでアクセスできるようにしたほうがいい気がする.し,それであればMetalLBとか使えるんでないか?とちょっと思っている.

ので今度試そう.

が,とりあえずCDとしての利用は十分にできる状態になった. ちなみにデプロイが必要なときだけVMを立ち上げればいいので,このPCは普段は立ち上げていない.