ArgoCD という Kubernetes 用の CD ツールがあります。
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
これを Istio Ingress Gateway と共に使う方法をまとめます。それだけでそこそこの量になったので。
ArgoCD の deploy
argocd という namespace を作って、そこに Manifest を apply するだけです。
$ kubectl create namespace argocd
$ kubectl apply -n argocd -f [https://raw.githubusercontent.com/argoproj/argo-cd/v1.4.2/manifests/install.yaml](https://raw.githubusercontent.com/argoproj/argo-cd/v1.4.2/manifests/install.yaml)
これだけで起動します。次のように port-forward すれば https://localhost:8443/ でアクセスできます。
$ kubectl -n argocd port-forward svc/argocd-server 8443:443
HA 構成の場合は manifests/ha/install.yaml を使うようです。
$ diff -u \
<(curl -s https://raw.githubusercontent.com/argoproj/argo-cd/v1.4.2/manifests/install.yaml) \
<(curl -s https://raw.githubusercontent.com/argoproj/argo-cd/v1.4.2/manifests/ha/install.yaml)
HA の方は Redis sentinel で Redis が冗長構成になるようです。
ArgoCD 用 Istio Ingress の設定
ArgoCD は cli 用の gRPC とブラウザ向けの HTTP を同じサーバー、同じポートで処理しており、そこが Ingress 設定におけるポイントです。
TLS Passthrough
argocd-server はデフォルトで TLS 対応しているため、これをそのまま活かす方法です。
Gateway で port 443 を tls.mode: PASSTHROUGH
とします。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: argocd-gw
namespace: argocd
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- argocd.example.com
port:
name: http
number: 80
protocol: HTTP
- hosts:
- argocd.example.com
port:
number: 443
name: https
protocol: HTTPS
tls:
mode: PASSTHROUGH
VirtualService は argocd-gw (Gateway) と紐付け、argocd.example.com 宛て (https では SNI が必須) を argocd-server (Service) に転送します。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: argocd-vsvc
namespace: argocd
spec:
gateways:
- argocd-gw
hosts:
- argocd.example.com
http:
- name: argocd-http
route:
- destination:
host: argocd-server
tls:
- name: argocd-https
match:
- port: 443
sniHosts:
- argocd.example.com
route:
- destination:
host: argocd-server
argocd の argocd-secret
Secret に入っている証明書 (tls.crt と tls.key) を更新する必要があります。
argocd cli からもアクセス可能です。
$ argocd --server argocd.example.com:443 app list
TLS Termination (方法1)
Ingress で TLS を Termination した場合の設定方法です。argocd-server (Pod) へのアクセスは TLS を使わないため、argocd-server Deployment の設定を変更して argocd-server の起動オプションに --insecure
を追加する必要があります。
$ kubectl -n argocd edit deployment argocd-server
command に --insecure
を追加します。これを追加しないと argocd-server が https でのアクセスを求めて redirect loop となります。
$ kubectl -n argocd patch deployment argocd-server -p '
{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "argocd-server",
"command": ["argocd-server","--staticassets","/shared/app","--insecure"]
}
]
}
}
}
}'
template:
spec:
containers:
- command:
- argocd-server
- --staticassets
- /shared/app
- --insecure
Gateway で argocd.example.com を port 80 と port 443 で受け入れます。443 は tls.mode を SIMPLE とします。TLS の証明書と秘密鍵が必要となりますが、 istio-system namespace に argocd-certificate という名前の Secret が事前に作成されている前提です(ここの詳しい話は以前の投稿を参照)。argocd-server が --insecure
の影響で https への redirect を行わなくなっているため、Gateway で port 80 のところに tls.httpsRedirect: true
を入れてあります。これで 301 Redirect を返してくれます。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: argocd-gw
namespace: argocd
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- argocd.example.com
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- argocd.example.com
port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: argocd-certificate
VirtualService で argocd.example.com 宛てを argocd-server (Service) に送ります。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: argocd-vsvc
namespace: argocd
spec:
gateways:
- argocd-gw
hosts:
- argocd.example.com
http:
- name: http
route:
- destination:
host: argocd-server
この方法では Ingress の Envoy と ArgoCD Pod の間を gRPC として処理しないため、argocd cli からアクセスする場合に --grpc-web
オプションの指定が必要になります。
$ argocd --server argocd.example.com:443 --grpc-web app list
--grpc-web
オプションをつけないと次のようなエラーとなります。
FATA[0000] rpc error: code = Internal desc = transport: received the unexpected content-type "text/plain; charset=utf-8"
TLS Termination (方法2)
先の方法(方法1)では gRPC が使えなくなってしまいましたが、User-Agent で判断して argocd コマンドからの場合は gRPC でアクセスできるようにします。
方法1と同じく argocd-server に --insecure
の追加が必要です。
$ kubectl -n argocd patch deployment argocd-server -p '
{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "argocd-server",
"command": ["argocd-server","--staticassets","/shared/app","--insecure"]
}
]
}
}
}
}'
さらに、argocd の manifest で作成されている argocd-server Service も編集します。port 443 の name を grpc に変更します。名前が重要。
$ kubectl -n argocd edit svc argocd-server
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
- **name: grpc**
port: 443
protocol: TCP
targetPort: 8080
その上で、Gateway と VirtualServer を作成する
Gateway は方法1と同じ
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: argocd-gw
namespace: argocd
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- argocd.example.com
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- argocd.example.com
port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: argocd-certificate
VirtualService では User-Agent が argocd-client で始まる場合は grpc に名前を変更した port 443 に、それ意外は port 80 へ。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: argocd-vsvc
namespace: argocd
spec:
gateways:
- argocd-gw
hosts:
- argocd.example.com
http:
- name: grpc
match:
- headers:
user-agent:
prefix: argocd-client
route:
- destination:
host: argocd-server
port:
number: 443
- name: http
route:
- destination:
host: argocd-server
port:
number: 80
これでブラウザでも argocd cli からでも --grpc-web
オプションなしでアクセス可能です。