はじめに
Oracle Cloud では、Oracle Container Engine for Kubernetes (OKE) という名前のKubernetesのマネージドサービスを提供しています。この記事では、OKE の ServiceType : LoadBalancer を Let's Encrypt を使用して無料でSSL公開を行う手順を確認します。
前提
以下の手順を参考に、Let's Encrypt から SSL証明書を発行していることを前提としてます。
https://qiita.com/sugimount/items/3f43c55141252f8f2968#lets-encrypt%E3%81%A7ssl%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E5%85%A5%E6%89%8B
具体的には、上記リンクにも記載していますが、以下のように SSL証明書を取得していることを前提としています。
# ls -la /etc/letsencrypt/live/test.sugi.tokyo/
total 4
drwxr-xr-x 1 root root 512 Feb 10 05:56 .
drwx------ 1 root root 512 Feb 10 05:56 ..
-rw-r--r-- 1 root root 692 Feb 10 05:56 README
lrwxrwxrwx 1 root root 39 Feb 10 05:56 cert.pem -> ../../archive/test.sugi.tokyo/cert1.pem
lrwxrwxrwx 1 root root 40 Feb 10 05:56 chain.pem -> ../../archive/test.sugi.tokyo/chain1.pem
lrwxrwxrwx 1 root root 44 Feb 10 05:56 fullchain.pem -> ../../archive/test.sugi.tokyo/fullchain1.pem
lrwxrwxrwx 1 root root 42 Feb 10 05:56 privkey.pem -> ../../archive/test.sugi.tokyo/privkey1.pem
OKEを構築
@hhiroshellさんの以下の記事を参考にしてOKEクラスタを作ります
HTTPでアクセス
まずは、HTTPを使用して公開方法を確認します。
Nginx の Deployment マニフェストを作成
string trim '
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx
' > ~/workdir/nginx-http.yaml
applyします
kubectl apply -f ~/workdir/nginx-http.yaml
Kubernetes 上では、ServiceType : LoadBalancer が作成開始されて、OCI上で Load Balancer が作成されるのを Pending しています
> kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m <none>
my-nginx-svc LoadBalancer 10.96.65.55 <pending> 80:31886/TCP 29s app=nginx
OCI上で Load Balancer が作成語、Load Balancerの Global IP が EXTERNAL-IP に出力されます
> kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18m <none>
my-nginx-svc LoadBalancer 10.96.65.55 129.213.71.130 80:31886/TCP 1m app=nginx
curlでアクセスすると、NginxのWelcomeページが表示されています
> curl http://129.213.71.130/
<!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>
参考として、OCIのLoadBalancerの詳細情報を確認します。
backends には、各Nodeに対して 31886 が割り当ててあるので、LoadBalancerの後ろにはNodePort的なものが動いている様子が見えます。
LBの通信帯域が 100MB
となっている点も気になります。
なお、 Annotation を指定することで、通信帯域を含めた様々なパラメータを変更できるようです。
https://github.com/oracle/oci-cloud-controller-manager/blob/master/docs/load-balancer-annotations.md
> oci lb load-balancer list
{
"data": [
{
"backend-sets": {
"TCP-80": {
"backends": [
{
"backup": false,
"drain": false,
"ip-address": "10.0.64.2",
"name": "10.0.64.2:31886",
"offline": false,
"port": 31886,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.96.2",
"name": "10.0.96.2:31886",
"offline": false,
"port": 31886,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.32.2",
"name": "10.0.32.2:31886",
"offline": false,
"port": 31886,
"weight": 1
}
],
"health-checker": {
"interval-in-millis": 10000,
"port": 10256,
"protocol": "HTTP",
"response-body-regex": ".*",
"retries": 3,
"return-code": 200,
"timeout-in-millis": 3000,
"url-path": "/healthz"
},
"name": "TCP-80",
"policy": "ROUND_ROBIN",
"session-persistence-configuration": null,
"ssl-configuration": null
}
},
"certificates": {},
"compartment-id": "ocid1.tenancy.oc1..aaaaaaaaqhjag3s37bdq6b6pc4f6lyc6bvcxdisqjzsd6tpks3ablacdwnaa",
"defined-tags": {},
"display-name": "c3758617-2cec-11e9-8f6f-0a580aed26c3",
"freeform-tags": {},
"hostnames": {},
"id": "ocid1.loadbalancer.oc1.iad.aaaaaaaab376decncoxe7klxldwffgre4wzj5acldfnesc5lljntlkuk22oa",
"ip-addresses": [
{
"ip-address": "129.213.71.130",
"is-public": true
}
],
"is-private": false,
"lifecycle-state": "ACTIVE",
"listeners": {
"TCP-80": {
"connection-configuration": {
"idle-timeout": 300
},
"default-backend-set-name": "TCP-80",
"hostname-names": null,
"name": "TCP-80",
"path-route-set-name": null,
"port": 80,
"protocol": "TCP",
"rule-set-names": [],
"ssl-configuration": null
}
},
"path-route-sets": {},
"rule-sets": {},
"shape-name": "100Mbps",
"subnet-ids": [
"ocid1.subnet.oc1.iad.aaaaaaaab4aso5kbx6f4ydo5o3xeg5ppdtf5zqczkd2p7jdr5jqqcuvyhznq",
"ocid1.subnet.oc1.iad.aaaaaaaatxkp55537gnqievnvohxdvjfipqpbvyrv2jhb5z53ootb3crzpua"
],
"time-created": "2019-02-10T04:31:45.245000+00:00"
}
]
}
確認できたので、削除をします
kubectl delete svc my-nginx-svc
kubectl delete deploy my-nginx
HTTPSでアクセス
以下のDocumentに、ServiceType : LoadBalancer を SSL 化する内容があります。これを参考に進めていきます。
https://docs.cloud.oracle.com/iaas/Content/ContEng/Tasks/contengcreatingloadbalancer.htm#creatinglbhttps
let's Encrypt から生成した SSL証明書のうち、cert.pem
と privkey.pem
を使用して、KubernetesのSecret を作成する必要があります。
# ls -la /etc/letsencrypt/live/test.sugi.tokyo/
total 4
drwxr-xr-x 1 root root 512 Feb 10 05:56 .
drwx------ 1 root root 512 Feb 10 05:56 ..
-rw-r--r-- 1 root root 692 Feb 10 05:56 README
lrwxrwxrwx 1 root root 39 Feb 10 05:56 cert.pem -> ../../archive/test.sugi.tokyo/cert1.pem # SSL/TLS サーバ証明書 (公開鍵を含む)
lrwxrwxrwx 1 root root 40 Feb 10 05:56 chain.pem -> ../../archive/test.sugi.tokyo/chain1.pem # 中間証明書
lrwxrwxrwx 1 root root 44 Feb 10 05:56 fullchain.pem -> ../../archive/test.sugi.tokyo/fullchain1.pem # サーバ証明書と中間証明書が結合されたもの
lrwxrwxrwx 1 root root 42 Feb 10 05:56 privkey.pem -> ../../archive/test.sugi.tokyo/privkey1.pem # 秘密鍵
kubectl でSecretをつくります
kubectl create secret tls ssl-certificate-secret --key privkey.pem --cert cert.pem
Deployment用のマニフェストファイルを作成します。大事なポイントは、LoadBalancerの annotation に、作成した Secret と port 443 を指定しているところです。
string trim '
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
annotations:
service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/oci-load-balancer-tls-secret: ssl-certificate-secret
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 80
' > ~/workdir/nginx-https.yaml
applyします
kubectl apply -f ~/workdir/nginx-https.yaml
以下のように Service が作成されるまで待機します
> kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16h <none>
nginx-service LoadBalancer 10.96.242.48 129.213.14.248 80:30797/TCP,443:31892/TCP 51s app=nginx
作成した EXTERNAL-IP を test.sugi.tokyo
に紐づくかたちで Aレコードを OCI DNS に作成します。JSONファイルを準備します
string trim '
[
{
"domain": "test.sugi.tokyo",
"is-protected": false,
"rdata": "129.213.14.248",
"rrset-version": "2",
"rtype": "A",
"ttl": 30
}
]
' > ~/workdir/test.sugi.tokyo.json
A レコードを作成
oci dns record domain patch --zone-name-or-id "sugi.tokyo" --domain "test.sugi.tokyo" --items file://~/workdir/test.sugi.tokyo.json
ブラウザからアクセステスト。
https://test.sugi.tokyo/
openssl
コマンドで見てみると、正常に動作しているように見えます
> openssl s_client -connect test.sugi.tokyo:443
CONNECTED(00000003)
depth=0 CN = test.sugi.tokyo
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = test.sugi.tokyo
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=test.sugi.tokyo
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
念のため、OCI LB 側の詳細を確認します
> oci lb load-balancer list
{
"data": [
{
"backend-sets": {
"TCP-443": {
"backends": [
{
"backup": false,
"drain": false,
"ip-address": "10.0.96.2",
"name": "10.0.96.2:31892",
"offline": false,
"port": 31892,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.64.2",
"name": "10.0.64.2:31892",
"offline": false,
"port": 31892,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.32.2",
"name": "10.0.32.2:31892",
"offline": false,
"port": 31892,
"weight": 1
}
],
"health-checker": {
"interval-in-millis": 10000,
"port": 10256,
"protocol": "TCP",
"response-body-regex": ".*",
"retries": 3,
"return-code": 200,
"timeout-in-millis": 3000,
"url-path": "/healthz"
},
"name": "TCP-443",
"policy": "ROUND_ROBIN",
"session-persistence-configuration": null,
"ssl-configuration": null
},
"TCP-80": {
"backends": [
{
"backup": false,
"drain": false,
"ip-address": "10.0.96.2",
"name": "10.0.96.2:30797",
"offline": false,
"port": 30797,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.64.2",
"name": "10.0.64.2:30797",
"offline": false,
"port": 30797,
"weight": 1
},
{
"backup": false,
"drain": false,
"ip-address": "10.0.32.2",
"name": "10.0.32.2:30797",
"offline": false,
"port": 30797,
"weight": 1
}
],
"health-checker": {
"interval-in-millis": 10000,
"port": 10256,
"protocol": "HTTP",
"response-body-regex": ".*",
"retries": 3,
"return-code": 200,
"timeout-in-millis": 3000,
"url-path": "/healthz"
},
"name": "TCP-80",
"policy": "ROUND_ROBIN",
"session-persistence-configuration": null,
"ssl-configuration": null
}
},
"certificates": {
"ssl-certificate-secret": {
"ca-certificate": "",
"certificate-name": "ssl-certificate-secret",
"public-certificate": "-----BEGIN CERTIFICATE-----secret-----END CERTIFICATE-----\n"
}
},
"compartment-id": "ocid1.tenancy.oc1..aaaaaaaaqhjag3s37bdq6b6pc4f6lyc6bvcxdisqjzsd6tpks3ablacdwnaa",
"defined-tags": {},
"display-name": "e9a507c8-2d77-11e9-8f6f-0a580aed26c3",
"freeform-tags": {},
"hostnames": {},
"id": "ocid1.loadbalancer.oc1.iad.aaaaaaaaqq4ouav4yrccvxh2p26xzjpwc6mqyt3dgbbdio4hauylgp4oaaca",
"ip-addresses": [
{
"ip-address": "129.213.14.248",
"is-public": true
}
],
"is-private": false,
"lifecycle-state": "ACTIVE",
"listeners": {
"TCP-443-ssl-certificate-secret": {
"connection-configuration": {
"idle-timeout": 300
},
"default-backend-set-name": "TCP-443",
"hostname-names": null,
"name": "TCP-443-ssl-certificate-secret",
"path-route-set-name": null,
"port": 443,
"protocol": "TCP",
"rule-set-names": [],
"ssl-configuration": {
"certificate-name": "ssl-certificate-secret",
"verify-depth": 0,
"verify-peer-certificate": false
}
},
"TCP-80": {
"connection-configuration": {
"idle-timeout": 300
},
"default-backend-set-name": "TCP-80",
"hostname-names": null,
"name": "TCP-80",
"path-route-set-name": null,
"port": 80,
"protocol": "TCP",
"rule-set-names": [],
"ssl-configuration": null
}
},
"path-route-sets": {},
"rule-sets": {},
"shape-name": "100Mbps",
"subnet-ids": [
"ocid1.subnet.oc1.iad.aaaaaaaab4aso5kbx6f4ydo5o3xeg5ppdtf5zqczkd2p7jdr5jqqcuvyhznq",
"ocid1.subnet.oc1.iad.aaaaaaaatxkp55537gnqievnvohxdvjfipqpbvyrv2jhb5z53ootb3crzpua"
],
"time-created": "2019-02-10T21:07:46.290000+00:00"
}
]
}
CERTNAMEなどが以下の指定となっている
SSL証明書の更新
Let's Encrypt は、90日で有効期限か切れるため、SSL証明書を定期的に入れ替える必要があります。
そこで、OCI側のLoadBalancer のSSL証明書の更新方法を確認します。
Documentに記載がないため、こういうパターンがあるなあと考えたものを載せています。
- 新たな Secret を生成して切り替える (アクセス断10秒以上あり。つらい)
- 直接更新パターン (アクセス断無し)
- 新たなLBを作ってDNSを切り替えるパターン (アクセス断無し)
2番が一番良い方法な気がします。
3番はDNSの、いわゆる浸透問題が発生する可能性があるので、2番が良いのかなと思います。
3番を採用した場合、AレコードのTTLの期間と、LBの並列稼働時間を調整すると、イイカンジに対処は出来るので、まあ、どっちでもいいのかな・・・?
新たな Secret を生成して切り替える (アクセス断有り)
OKE 上であらたな Secret を生成して、それに切り替える方法です。
現在の挙動では、アクセス断が10秒以上発生するため、採用しにくい方法となりますが、Kubernetesの操作だけで完結するため、わかりやすいメリットはあります。
Let's Encrypt で新しいSSL証明書を取得したのちに、以下の作業が必要になります。
OKE 上で 新しいSSL証明書を使用して、新たにSecret を作成します。
今回はわかりやすさのために ssl-certificate-secret-next
という名前でSecretを作成します。
kubectl create secret tls ssl-certificate-secret-next --key privkey.pem --cert cert.pem
マニフェストを新たに作成します。ポイントは、Service LoadBalancer の annotation で指定する service.beta.kubernetes.io/oci-load-balancer-tls-secret
を新たな Secret ssl-certificate-secret-next
に指定しているところです。
string trim '
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
annotations:
service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/oci-load-balancer-tls-secret: ssl-certificate-secret-next
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 80
' > ~/workdir/nginx-https.yaml
kubectl apply -f ~/workdir/nginx-https.yaml
この作業により、OCIのLoadBalancer上で、新たなSecretを新たな Certificates として登録されます。
しかし、この時に、OCI上のLoadBalancerの Listener(TCP443) が削除されて、新たな Certificates を持った Listener が再作成される挙動となり、
LoadBalancerの通信が、10秒ほど遮断されます。これはなかなか厳しい挙動です。
GitHub上の Issue として認識はされているようですが、解決はされていない様子です。
https://github.com/oracle/oci-cloud-controller-manager/issues/14
OCI LB を直接編集するパターン (アクセス断無し)
OCI LB を直接編集して、SSL証明書を切り替えるパターンです。
まず、編集したい Service LoadBalancer の EXTERNAL-IP を確認して、このIPアドレスを保有している OCI LB を特定します。
> kubectl get svc -o wide 815ms
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17h <none>
nginx-service LoadBalancer 10.96.242.48 129.213.14.248 80:30797/TCP,443:31892/TCP 36m app=nginx
OCI と jq コマンドで EXTERNAL-IP と一致しているものを検索して、OCID と 名前 と 作成時間を取得します
> oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[] | ."id", ."display-name", ."time-created" , ."listeners"'
ocid1.loadbalancer.oc1.iad.aaaaaaaaqq4ouav4yrccvxh2p26xzjpwc6mqyt3dgbbdio4hauylgp4oaaca
e9a507c8-2d77-11e9-8f6f-0a580aed26c3
2019-02-10T21:07:46.290000+00:00
LB の OCID を変数に入れます
set lb_ocid (oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[].id')
LBに紐づく TCP443 の Listenerに関する値を確認します。この後の手順で、Listenerを更新して新たなSSL証明を指定する必要があり、そのために必要な情報を確認します。
> oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[]."listeners"'
{
"TCP-443-ssl-certificate-secret-next2": {
"connection-configuration": {
"idle-timeout": 300
},
"default-backend-set-name": "TCP-443", <==================== 必要な値
"hostname-names": null,
"name": "TCP-443-ssl-certificate-secret-next2", <=========== 必要な値
"path-route-set-name": null,
"port": 443, <============================================== 必要な値
"protocol": "TCP", <======================================== 必要な値
"rule-set-names": [],
"ssl-configuration": {
"certificate-name": "ssl-certificate-secret-next2",
"verify-depth": 0,
"verify-peer-certificate": false
}
},
"TCP-80": {
"connection-configuration": {
"idle-timeout": 300
},
"default-backend-set-name": "TCP-80",
"hostname-names": null,
"name": "TCP-80",
"path-route-set-name": null,
"port": 80,
"protocol": "TCP",
"rule-set-names": [],
"ssl-configuration": null
}
}
必要な値をそれぞれ変数に入れます。jqのフィルター条件をふんわり書くと以下の条件指定を行っている
- OCI LB で、Public IP "129.213.14.248" を持っているものを指定
- 該当のLBに存在している Listener の中から、"default-backend-set-name" が "TCP-443" の値を持っているものを指定
set default_backend_set_name (echo "TCP-443")
set listener_name (oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[].listeners[] | select(."default-backend-set-name" == "TCP-443").name')
set listener_port (oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[].listeners[] | select(."default-backend-set-name" == "TCP-443").port')
set listener_protocol (oci lb load-balancer list | jq -r '.data | map(select(."ip-addresses"[0]."ip-address" == "129.213.14.248"))[].listeners[] | select(."default-backend-set-name" == "TCP-443").protocol')
LB に 新しいSSL証明書を指定して作成します。名前は manual_cert
とします
oci lb certificate create --certificate-name "manual_cert" --load-balancer-id $lb_ocid --private-key-file /home/sugi/ssl/privkey.pem --public-certificate-file /home/sugi/ssl/cert.pem
既存のListenerのSSL証明書を、新たに作成した manual_cert
へ切り替えます
oci lb listener update --load-balancer-id $lb_ocid --default-backend-set-name $default_backend_set_name --port $listener_port --protocol $listener_protocol --listener-name $listener_name --ssl-certificate-name "manual_cert" --force
念のため、OKE 上の Secret も同一名称で新たなSSL証明書を使って上書きします。kubectl create で上書きはできないため、 dry-run と -o yaml でマニフェストファイルを生成したのちに apply する方法で上書きします。
kubectl create secret tls ssl-certificate-secret --key tls.key --cert tls.crt --dry-run -o yaml | kubectl apply -f -
新たなLBを作成して、DNSを切り替えるパターン (アクセス断無し)
新たな Service LoadBalancer を作成して、OCI DNS で宛先を切り替えます
まずは、新たな Secret を作成します
kubectl create secret tls ssl-certificate-secret-next --key privkey.pem --cert cert.pem
新たなマニフェストファイルを作ります
string trim '
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service-next
annotations:
service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/oci-load-balancer-tls-secret: ssl-certificate-secret-next
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 80
' > ~/workdir/nginx-https-nextlb.yaml
kubectl apply -f ~/workdir/nginx-https-nextlb.yaml
新たな Service LoadBalancer が作成されます
> kubectl get svc -o wide 7s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18h <none>
nginx-service LoadBalancer 10.96.242.48 129.213.14.248 80:30797/TCP,443:31892/TCP 1h app=nginx
nginx-service-next LoadBalancer 10.96.75.66 <pending> 80:31323/TCP,443:31455/TCP 7s app=nginx
EXTERNAL-IP が作成されます
> kubectl get svc -o wide 1696ms
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18h <none>
nginx-service LoadBalancer 10.96.242.48 129.213.14.248 80:30797/TCP,443:31892/TCP 1h app=nginx
nginx-service-next LoadBalancer 10.96.75.66 129.213.179.197 80:31323/TCP,443:31455/TCP 44s app=nginx
DNSを切り替えて、新たな External IP に接続するようにします
作成した EXTERNAL-IP を test.sugi.tokyo
に紐づくかたちで Aレコードを OCI DNS に作成します。JSONファイルを準備します
string trim '
[
{
"domain": "test.sugi.tokyo",
"is-protected": false,
"rdata": "129.213.179.197",
"rrset-version": "2",
"rtype": "A",
"ttl": 30
}
]
' > ~/workdir/test.sugi.tokyo.json
A レコードを作成
oci dns record domain update --zone-name-or-id "sugi.tokyo" --domain "test.sugi.tokyo" --items file://~/workdir/test.sugi.tokyo.json --force
新たな Aレコードで名前解決が出来ています
> dig +dnssec @8.8.8.8 test.sugi.tokyo. A 801ms
; <<>> DiG 9.11.3-1ubuntu1.1-Ubuntu <<>> +dnssec @8.8.8.8 test.sugi.tokyo. A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45973
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;test.sugi.tokyo. IN A
;; ANSWER SECTION:
test.sugi.tokyo. 29 IN A 129.213.179.197
;; Query time: 158 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Feb 11 08:04:20 DST 2019
;; MSG SIZE rcvd: 60
curl でアクセス可能です
> curl --insecure https://test.sugi.tokyo/ 249ms<!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>
openssl コマンドでも正常に確認できています
> openssl s_client -connect test.sugi.tokyo:443 835msCONNECTED(00000003)
depth=0 CN = test.sugi.tokyo
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = test.sugi.tokyo
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=test.sugi.tokyo
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
備忘録
新規作成時につくった Secret をそのまま上書きしても、OCI LB 上の証明書は更新されない。あらたな名前でSecret を作成する必要がある。
具体例を挙げると、以下のように上書きしても意味がない
kubectl create secret tls ssl-certificate-secret --key tls.key --cert tls.crt --dry-run -o yaml | kubectl apply -f -
参考URL
Oracle Document
https://docs.cloud.oracle.com/iaas/Content/ContEng/Tasks/contengcreatingloadbalancer.htm#creatinglbhttps
OKEで指定できるアノテーション
https://github.com/oracle/oci-cloud-controller-manager/blob/master/docs/load-balancer-annotations.md
SSL証明書の形式変換
https://glorificatio.org/archives/2914