元ネタ
準備
-
Azure Kubernetes Service(AKS)を使って、K8sクラスタを作成する
- Helmをクライアントに入れて、サーバ側にtillerを入れるところまで。
- RBAC が有効になっているクラスタ。
- Helmをクライアントに入れて、サーバ側にtillerを入れるところまで。
注意
- 静的パブリック IP アドレスは、お金がかかる
-
パブリック IP アドレスの料金のページを参照。
- 最初の 5 つは0.5円/時間ぐらい(2019-04-29現在)。0.5円*24時間*30.5日=366円/月ぐらいか。
-
パブリック IP アドレスの料金のページを参照。
- AKS クラスターを削除すると、静的パブリック IP アドレスも解放されて消えてしまうので注意。
静的IPアドレスを取得する
-
AKS クラスターのリソース グループ名を取得
-
AKS_NODE_RES_GROUP=`az aks show --resource-group $AKS_RES_GROUP --name $AKS_CLUSTER_NAME --query nodeResourceGroup -o tsv`
-
-
静的パブリック IP アドレスを作成
-
az network public-ip create --resource-group $AKS_NODE_RES_GROUP --name myAKSPublicIP --allocation-method static
- 上記では名前を
myAKSPublicIP
にしているが、適宜変更。
- 上記では名前を
-
-
作成した静的パブリック IP アドレスを確認
-
az network public-ip list --query [].ipAddress
- 複数ある場合は、後々の設定でハマるので、ポータルから「パブリック IP アドレス 」で探して削除する。
PUBLIC_IP_ADDRESS=`az network public-ip list --query [].ipAddress -o tsv`
-
nginx-ingress をIPアドレス指定でインストール
- インストール
- namespaceを
kube-system
にしている。サンプルによってはkube-public
にしている場合もあるので注意。
- namespaceを
helm install stable/nginx-ingress \
--namespace kube-system \
--set controller.service.loadBalancerIP=$PUBLIC_IP_ADDRESS
- パブリックIPを確認
-
kubectl get service -l app=nginx-ingress --namespace kube-system
-
EXTERNAL-IP
が<pending>
の場合は、少し待つ。
-
-
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
excited-starfish-nginx-ingress-controller LoadBalancer 10.0.14.43 40.115.xxx.xxx 80:30202/TCP,443:31925/TCP 1m
excited-starfish-nginx-ingress-default-backend ClusterIP 10.0.121.158 <none> 80/TCP 1m
- ブラウザで、上記の40.115.xxx.xxxにアクセスする
-
default backend - 404
のように、デフォルトの404ページが表示される(起動に数分かかるので待つ)
-
DNS上の名前を決めて、設定
DNSNAME="my-aks-ingress-test123"
PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$PUBLIC_IP_ADDRESS')].[id]" --output tsv)
az network public-ip update --ids $PUBLICIPID --dns-name $DNSNAME
-
これでFQDNを使ってアクセスできるようになったので、ブラウザで開いて確認する
-
http://my-aks-ingress-test123.japaneast.cloudapp.azure.com/
-
default backend - 404
が出ればOK。
-
-
http://my-aks-ingress-test123.japaneast.cloudapp.azure.com/
cert-manager をインストール
- Let's Encrypt 証明書を自動的に作成および管理する機能を提供する
cert-manager
を入れる- 0.7.2が出ているので、0.6ではなく0.7を使う。
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/00-crds.yaml
- cert-manager用に名前空間を作成(
kube-system
ではなくcert-manager
という名前空間に入れる)kubectl create namespace cert-manager
-
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
-
disable-validation=true
を付けないと発行者が不明になって証明書が作成されない??
-
- helmを使ってインストールする(GitHubのcert-managerのページ を見ると0.7.2が最新なのでバージョン指定する際は確認する)
helm repo add jetstack https://charts.jetstack.io
helm repo update
- 0.7.2が出ているので、0.6ではなく0.7を使う。
helm install \
--name cert-manager \
--namespace cert-manager \
--version v0.7.2 \
jetstack/cert-manager
-
本番環境の場合は、--set ingressShim.extraArgs='{--default-issuer-name=letsencrypt-prod,--default-issuer-kind=ClusterIssuer}'
も付ける。- 下記の例では名前空間
kube-system
に入れている webhook.enables=false
を書かないと証明書が発行されないという情報もあるので追記-
stable/cert-manager
だとうまくいかなかったのでjetstack/cert-manager
を使った
- 下記の例では名前空間
- 上記で証明書を入れられたので、下記は参考。
helm install jetstack/cert-manager \
--name cert-manager \
--namespace kube-system \
--set ingressShim.defaultIssuerName=letsencrypt-prod \
--set ingressShim.defaultIssuerKind=ClusterIssuer \
--set webhook.enabled=false
-
入れ間違えたら、
helm delete --purge cert-manager
で消して入れ直し。- Error: customresourcedefinitions.apiextensions.k8s.io "certificates.certmanager.k8s.io" already exists の場合は、
kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/00-crds.yaml
で消す
- Error: customresourcedefinitions.apiextensions.k8s.io "certificates.certmanager.k8s.io" already exists の場合は、
-
これだけで(信頼されない)証明書が発行されるので、ブラウザでHTTPSで接続して確認する
-
https://my-aks-ingress-test123.japaneast.cloudapp.azure.com/
- 信頼されない証明書の警告がでるので、適宜スルーする
- Common Nameは
Kubernetes Ingress Controller Fake Certificate
になる
-
https://my-aks-ingress-test123.japaneast.cloudapp.azure.com/
CA クラスター発行者を作成
-
cluster-issuer.yaml
ファイルを以下の内容で作成 -
email
を、実際のメールアドレスに変更する - テスト用なので、
staging
を使用する。本番環境ではletsencrypt-prod
とhttps://acme-v02.api.letsencrypt.org/directory
を使用する- サーバはv01ではなくv02を使わないと、ずっと
Issuer letsencrypt-staging not ready
のままで原因が分かりづらい。-
kubectl describe clusterissuer letsencrypt-staging
やkubectl describe clusterissuer letsencrypt-prod
で状況を確認。
-
- サーバはv01ではなくv02を使わないと、ずっと
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
#name: letsencrypt-prod
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
#server: https://acme-v02.api.letsencrypt.org/directory
email: user@example.com
privateKeySecretRef:
name: letsencrypt-staging
#name: letsencrypt-prod
http01: {}
-
kubectl apply -f cluster-issuer.yaml
で適用-
Error from server (InternalError): error when creating "cluster-issuer.yaml": Internal error occurred: failed calling admission webhook "clusterissuers.admission.certmanager.k8s.io": the server is currently unable to handle the request
と表示されたら、しばらく待ってもう一度行う
-
デモ アプリを入れる
- デフォルトの404ページで動作確認しようとしてはまったので、デモ アプリを入れる
helm repo add azure-samples https://azure-samples.github.io/helm-charts/
helm install azure-samples/aks-helloworld --namespace ingress-basic
helm list --namespace ingress-basic
helm install azure-samples/aks-helloworld --namespace ingress-basic --set title="AKS Ingress Demo" --set serviceName="ingress-demo"
helm list --namespace ingress-basic
イングレス ルートを作成
-
hello-world-ingress.yaml
を以下で作成 -
hosts
やhost
は自分のホスト名に変更する
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-world-ingress
namespace: ingress-basic
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- my-aks-ingress-test123.japaneast.cloudapp.azure.com
secretName: tls-secret
rules:
- host: my-aks-ingress-test123.japaneast.cloudapp.azure.com
http:
paths:
- path: /
backend:
serviceName: aks-helloworld
servicePort: 80
- path: /hello-world-two
backend:
serviceName: ingress-demo
servicePort: 80
-
kubectl apply -f hello-world-ingress.yaml
で適用
証明書の確認
-
上記で自動的に要求される
kubectl describe certificate tls-secret --namespace ingress-basic
kubectl describe certificate tls-secret
-
kubectl describe certificate
で状況確認-
OrderCreated
が無ければ、cert-manager の証明書についてのページやOrdersを見ながら、証明書を要求
-
kubectl describe order
- ずっと
Issuer letsencrypt-prod not ready
のままの場合、kubectl describe clusterissuer letsencrypt-staging
やkubectl describe clusterissuer letsencrypt-prod
で状況を確認。- 引数は
cluster-issuer
ではなくclusterissuer
なので注意
- 引数は
kubectl describe clusterissuer letsencrypt-prod
で状態が表示できる
(略)
Status:
Acme:
Uri: https://acme-v02.api.letsencrypt.org/acme/acct/56269408
Conditions:
Last Transition Time: 2019-05-02T07:29:25Z
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Events: <none>
-
kubectl describe certificate tls-secret --namespace ingress-basic
で以下のようにイベント詳細が表示できる
(略)
Status:
Conditions:
Last Transition Time: 2019-05-02T07:29:51Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
Not After: 2019-07-31T06:29:50Z
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning IssuerNotFound 3m44s cert-manager clusterissuer.certmanager.k8s.io "letsencrypt-prod" not found
Warning IssuerNotReady 3m28s (x3 over 7m31s) cert-manager Issuer letsencrypt-prod not ready
Normal Generated 3m27s cert-manager Generated new private key
Normal GenerateSelfSigned 3m27s cert-manager Generated temporary self signed certificate
Normal OrderCreated 3m27s cert-manager Created Order resource "tls-secret-224255xxxx"
Normal OrderComplete 3m1s cert-manager Order "tls-secret-224255xxxx" completed successfully
Normal CertIssued 3m1s cert-manager Certificate issued successfully
-
ステータスが
Certificate issuance in progress. Temporary certificate issued.
の場合は、しばらく待つ。- Temporary certificateが発行されてから、本物のcertificateが発行される。という順番なので、ステータスで確認。
chromeの開発者ツールのSecurityで見ると、
Certificate - valid and trusted
の下に
The connection to this site is using a valid, trusted server certificate issued by 不明な名前.
となっている場合がある。対処方法不明。
ブラウザで表示して、証明書の確認
-
https://my-aks-ingress-test123.japaneast.cloudapp.azure.com のように、HTTPSでつないで、証明書の確認
- Common Name(CN)が、
my-aks-ingress-test123.japaneast.cloudapp.azure.com
のように、 自分のホスト名になる。
- Common Name(CN)が、
- https://my-aks-ingress-test123.japaneast.cloudapp.azure.com/hello-world-two では、2つ目のデモアプリ(画像と文言が少し違う)が表示される
証明書オブジェクトを作成(必要に応じて)
-
certificates.yaml
ファイルを以下の内容で作成。 -
dnsNames
とdomains
を前の手順で作成した DNS 名に変更する
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: tls-secret
spec:
secretName: tls-secret
dnsNames:
- my-aks-ingress-test123.japaneast.cloudapp.azure.com
acme:
config:
- http01:
ingressClass: nginx
domains:
- my-aks-ingress-test123.japaneast.cloudapp.azure.com
issuerRef:
name: letsencrypt-staging
#name: letsencrypt-prod
kind: ClusterIssuer
-
kubectl apply -f certificates.yaml
で適用。