[HARDWAY] 04. Provisioning a CA and Generating TLS Certificates
https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/04-certificate-authority.md
인증서를 생성하도록 하자
인증서는 만들것도 많고, 햇갈릴수 있는 부분이니 꼼꼼히 작업해야한다.
### Certificate Authority
# ca-config.json 파일 생성
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF
# ca-csr.json 파일 생성
cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF
# ca 인증서 생성
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
[root@master01 ~]# ll ca*
-rw-r--r--. 1 root root 232 Nov 23 10:51 ca-config.json
-rw-r--r--. 1 root root 1005 Nov 23 10:51 ca.csr
-rw-r--r--. 1 root root 211 Nov 23 10:51 ca-csr.json
-rw-------. 1 root root 1679 Nov 23 13:26 ca-key.pem
-rw-r--r--. 1 root root 1318 Nov 23 13:26 ca.pem
[root@master01 ~]#
ca-config.json, ca-csr.json (EOF 로 파일 직접생성), ca.csr, ca.pem, ca-key.pem 파일이 있어야 하며, 위의 파일중 ca.pem, ca-key.pem 파일을 사용한다.
[root@master01 ~]# cat 001_create_ca.sh
#!/bin/bash
### CA Create
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
### Client and Server Certificates
# admin-csr.json 파일 생성
cat > admin-csr.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
# admin 인증서 생성
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
# 결과
# ll admin* | awk {'print $9'}
admin.csr
admin-csr.json
admin-key.pem
admin.pem
admin-csr.json (EOF 로 파일 직접생성), admin.csr, admin.pem, admin-key.pem 파일이 있어야 하며, 위의 파일중 admin.pem, admin-key.pem 파일을 사용한다.
[root@master01 ~]# cat 002_admin_certificate.sh
#!/bin/bash
cat > admin-csr.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
이렇게 간단하게 스크립트로 생성하였다.
### The Kubelet Client Certificates
kubelet 에서 사용할 인증서로, 몇가지 IP(hostname) 정보가 필요하다.
External_IP 는 Master 의 외부노출(haproxy 구성예정) IP 이다.
INTERNAL_IP 는 Worker Node 의 자기자신 IP 이다.
instance 는 worker node 의 hostname 정보 이다.
[root@master01 ~]# cat 003_kubelet_client_certificate.sh
#!/bin/bash
EXTERNAL_IP=192.168.1.47
INTERNAL_IP=("192.168.1.57" "192.168.1.58" "192.168.1.60")
instance=("worker01" "worker02" "worker03")
for ((i=0; i<3; i++)); do
cat > ${instance[i]}-csr.json <<EOF
{
"CN": "system:node:${instance[i]}",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:nodes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=${instance[i]},${INTERNAL_IP[i]},${EXTERNAL_IP} \
-profile=kubernetes \
${instance[i]}-csr.json | cfssljson -bare ${instance[i]}
done
위의 내용을 스크립트로 작성하여 sh 003_kubelet_client_certificate.sh 로 수행하였으며, 아래와 같은 인증서가 있어야 한다.
[root@master01 ~]# ll worker* | awk {'print $9'}
worker01.csr
worker01-csr.json
worker01-key.pem
worker01.pem
worker02.csr
worker02-csr.json
worker02-key.pem
worker02.pem
worker03.csr
worker03-csr.json
worker03-key.pem
worker03.pem
[root@master01 ~]# cat 004_controller-manager-certificate.sh
#!/bin/bash
cat > kube-controller-manager-csr.json <<EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:kube-controller-manager",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
sh 004_controller-manager-certificate.sh
# 확인
[root@master01 ~]# ll kube-controller* | awk {'print $9'}
kube-controller-manager.csr
kube-controller-manager-csr.json
kube-controller-manager-key.pem
kube-controller-manager.pem
### The Kube Proxy Client Certificate
[root@master01 ~]# cat 005_kube-proxy_client_certificate.sh
#!/bin/bash
cat > kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:node-proxier",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy
# 스크립트 생성 후 실행
sh 005_kube-proxy_client_certificate.sh
# 확인
[root@master01 ~]# ll kube-proxy* | awk {'print $9'}
kube-proxy.csr
kube-proxy-csr.json
kube-proxy-key.pem
kube-proxy.pem
### The Scheduler Client Certificate
[root@master01 ~]# cat 006_kube-scheduler_client_certificate.sh
#!/bin/bash
cat > kube-scheduler-csr.json <<EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:kube-scheduler",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-scheduler-csr.json | cfssljson -bare kube-scheduler
# 스크립트 생성 후 실행
sh 006_kube-scheduler_client_certificate.sh
# 확인
[root@master01 ~]# ll kube-scheduler* | awk {'print $9'}
kube-scheduler.csr
kube-scheduler-csr.json
kube-scheduler-key.pem
kube-scheduler.pem
### The Kubernetes API Server Certificate
EXTERNAL_IP 는 master 의 외부노출 IP 이다. (haproxy)
MASTER_IP 는 master node 의 각각의 IP 이다.
[root@master01 ~]# cat 007_apiserver_certificate.sh
#!/bin/bash
EXTERNAL_IP=192.168.1.47
MASTER_IP=192.168.1.21,192.168.1.55,192.168.1.56
KUBERNETES_HOSTNAMES=kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.svc.cluster.local
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=10.32.0.1,${MASTER_IP},127.0.0.1,${KUBERNETES_HOSTNAMES},${EXTERNAL_IP} \
-profile=kubernetes \
kubernetes-csr.json | cfssljson -bare kubernetes
# 스크립트 생성 후 실행
### The Service Account Key Pair
[root@master01 ~]# cat 008_service-account_certificate.sh
#!/bin/bash
cat > service-account-csr.json <<EOF
{
"CN": "service-accounts",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
service-account-csr.json | cfssljson -bare service-account
# 스크립트 생성 후 실행
### Distribute the Client and Server Certificates (인증서 배포)
[root@master01 ~]# cat 009_certificate_file_copy.sh
#!/bin/bash
WORKER=("worker01" "worker02" "worker03")
MASTER=("master01" "master02" "master03")
for ((i=0; i<3; i++)); do
scp ca.pem ${WORKER[i]}-key.pem ${WORKER[i]}.pem ${WORKER[i]}:~/
sleep 2
done
for ((i=0; i<3; i++)); do
scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
service-account-key.pem service-account.pem ${MASTER[i]}:~/
sleep 2
done
# 스크립트 생성 후 실행