In K8s, Kube-Apiserver uses ETCD for persistent storage of REST Object resources. This article introduces how to configure and generate self-signed HTTPS certificate, build ETCD cluster for Apiserver to use, and attach related pit records.
1. Install CFSSL
CD/data/work wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl_1.6.0_linux_amd64 - O CFSSL wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssljson_1.6.0_linux_amd64 - O cfssljson wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl-certinfo_1.6.0_linux_amd64 - O CFSSL - certinfo chmod + x cfssl* mv cfssl* /usr/local/bin/ chmod +x cfssl* mv cfssl_linux-amd64 /usr/local/bin/cfssl mv cfssljson_linux-amd64 /usr/local/bin/cfssljson mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfoCopy the code
2. Create a CA certificate
cat > ca-csr.json <<EOF { "CN": "etcd-ca", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Beijing", "L": "Beijing", "O": "etcd-ca", "OU": "etcd-ca" } ], "ca": { "expiry": "87600 h"}} EOF CFSSL gencert - initca ca - CSR. Json | cfssljson - bare ca = > generate: ca - key. Pem, ca. CSR, ca. PemCopy the code
3. Configure the CA certificate policy
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"etcd-ca": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF
Copy the code
4. Configure the ETCD to request a CSR
cat > etcd-csr.json <<EOF { "CN": "etcd", "hosts": [" 127.0.0.1 ", "etcd0-0. Etcd", "etcd1-0. Etcd", "etcd2-0. Etcd]", "key" : {" algo ":" rsa ", "size" : 2048}, "names" : [{ "C": "CN", "ST": "Beijing", "L": "Beijing", "O": "etcd", "OU": "etcd" }] } EOFCopy the code
5. Generate the ETCD certificate
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd-ca etcd-csr.json | cfssljson -bare etcd Pem, etcd. CSR, etcd.pemCopy the code
6. Create an etcd cluster
Yaml file: github.com/k8s-club/et…
kubectl apply -f etcd-cluster.yaml
Copy the code
7. View DNS resolution
Dnsutils installation: kubernetes. IO/docs/tasks /…
Kubectl exec it-n etcd dnsutils -- nslookup etcd Server: 9.165.x.x Address: 9.165.x.x#53 Name: kubectl exec it-n etcd dnsutils -- nslookup etcd Server: 9.165.x.x#53 Name: Etcd. Etcd. SVC. Cluster. The local Address: 9.165. 7.0.x.x Name: etcd. Etcd. SVC. Cluster. The local Address: 9.165. 7.0.x.x Name: Etcd. Etcd. SVC. Cluster. The local Address: 9.165. 7.0.x.xCopy the code
8. Check the ETCD cluster status
kubectl exec -it -n etcd etcd0-0 -- sh /usr/local/bin/etcdctl --write-out=table --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem --endpoints=https://etcd0-0.etcd:2379,https://etcd1-0.etcd:2379,https://etcd2-0.etcd:2379 endpoint health +---------------------------+--------+-------------+-------+ | ENDPOINT | HEALTH | TOOK | ERROR | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- + | | https://etcd0-0.etcd:2379 true 13.551982 ms | | | | https://etcd1-0.etcd:2379 | true 13.540498 ms | | | | | https://etcd2-0.etcd:2379 true 23.119639 ms | | | +---------------------------+--------+-------------+-------+ /usr/local/bin/etcdctl --write-out=table --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem --endpoints=https://etcd0-0.etcd:2379,https://etcd1-0.etcd:2379,https://etcd2-0.etcd:2379 endpoint status +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--- -----------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- + | | http://etcd0-0.etcd:2379 4 dde210279eea33a | 3.4.13 20 kB | | true | false | 2 | | | 9 9 20669865 d12a473b http://etcd1-0.etcd:2379 | | | | 3.4.13 | 20 kB | | false false | 2 | 9 9 | | | | F17922d1ed63113 http://etcd2-0.etcd:2379 | 3 | 3.4.13 20 kB | | | false false | 2 | | 9 9 | | +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--- -----------------+--------+Copy the code
9. Verify etCD read and write
kubectl exec -it -n etcd etcd0-0 -- sh /usr/local/bin/etcdctl --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem put hello world OK /usr/local/bin/etcdctl Pem --cert= /etc/etcd-ssl/etcd-key. pem --key= /etc/etcd-ssl/etcd-key. pem get hello hello world View all information keys: /usr/local/bin/etcdctl --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem get "" --keys-only --prefix hello /usr/local/bin/etcdctl --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem get "" --prefix hello worldCopy the code
10. Configure apiserver to request CSR
cat > apiserver-csr.json <<EOF
{
"CN": "apiserver",
"hosts": [
"*.etcd"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "apiserver",
"OU": "apiserver"
}]
}
EOF
Copy the code
11. Generate the Apiserver certificate
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd-ca apiserver-csr.json | cfssljson -bare Pem, apiserver. CSR, and apiserver.pem are generatedCopy the code
12. Create the extension – apiserver
Yaml: Use ConfigMap to mount the *. Pem certificate to Apiserver
containers:
- image: xxxxx:latest
args:
- --etcd-servers=https://etcd0-0.etcd:2379
- --etcd-cafile=/etc/kubernetes/certs/kube-apiserver-etcd-ca.crt
- --etcd-certfile=/etc/kubernetes/certs/kube-apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/certs/kube-apiserver-etcd-client.key
Copy the code
kubectl apply -f apiserver.yaml
Copy the code
13. Pothole record
13.1 The certificate hosts is incorrect
log: etcd0-0: {" level ":" warn ", "ts" : "the 2021-08-19 T11:55:07. 755 z", the "caller" : "embed/config_logging. Go: 279", "MSG" : "rejected Connection ", "remote - addr" : "127.0.0.1:41226" and "server - the name" : ""," error ":" the TLS. first record does not look like a TLS handshake"} etcd1-0: {" level ", "info", "ts" : "the 2021-08-19 T11: bloweth. 830 z", the "caller" : "embed/serve. Go: 191", "MSG" : "serving client traffic securely","address":"[::]:2379"} {" level ", "info", "ts" : "the 2021-08-19 T11: bloweth. 838 z", the "caller" : "etcdserver/server. Go: 716", "MSG" : "the initialized peer connections; fast-forwarding election Ticks ", "30 dd90df9a304e97 local - member - id" : ""," forward - ticks ": 18," forward - duration ":" 4.5 ", "s election - ticks" : 20, "election - t imeout":"5s","active-remote-members":2} {" level ", "info", "ts" : "the 2021-08-19 T11: bloweth. 867 z", the "caller" : "the membership/cluster. Go: 558", "MSG" : "set initial cluster Version ", "80 c7f1f6c2848777 cluster - id" : ""," local - member - id ":" 30 dd90df9a304e97 cluster - ", "version" : "3.4"} {" level ", "info", "ts" : "the 2021-08-19 T11: bloweth. 867 z", the "caller" : "API/capability. Go: 76", "MSG" : "enabled" capabilities for Version ", "cluster - version" : "3.4"} etcd2-0: {" level ":" warn ", "ts" : "the 2021-08-19 T11:54:17. 782 z", the "caller" : "embed/config_logging. Go: 270", "MSG" : "rejected Connection ", "remote - addr" : "9.165 7.0.x.x: 40180" and "server - the name" : "etcd2-0. Etcd", "IP addresses -" : [" 0.0.0.0 ", "127.0.0.1"], "DNS - nam es":["etcd0-0.etcd","etcd1-0.etcd","etcd2-0.etcd"],"error":"tls: \"9.165.x.x\" does not match any of DNSNames [\"etcd0-0.etcd\" \"etcd1-0.etcd\" \"etcd2-0.etcd\"] (lookup etcd1-0.etcd On 9.165.x.x:53: no such host)"}Copy the code
Solution: Reconfigure the correct hosts domain name
13.2 Certificate hosts Configuration Pits
"Hosts" : [" 127.0.0.1 ", "etcd0-0. Etcd", "*. Etcd" / / allow * generic domain name, but can't be empty "or" *].Copy the code
13.3 DNS Settings
You are advised to set *.xxx.ns. SVC, so that no revisa is required after capacity expansion
Reference: kubernetes. IO/docs/concep…
Go code reference is as follows:
func genEtcdWildcardDnsName(namespace, serviceName string) []string {
return []string{
fmt.Sprintf("%s.%s.%s", serviceName, namespace, "svc"),
fmt.Sprintf("*.%s.%s.%s", serviceName, namespace, "svc"),
fmt.Sprintf("%s.%s.%s", serviceName, namespace, DnsBase),
fmt.Sprintf("*.%s.%s.%s", serviceName, namespace, DnsBase),
}
}
Copy the code
13.4 The leader/ Follower is successfully established, but an access error occurs
# /usr/local/bin/etcdctl put hello world {" level ":" warn ", "ts" : "the 2021-08-19 T12: thus says. 200 z", the "caller" : "clientv3 / retry_interceptor. Go: 62", "MSG" : "retrying of unary invoker Failed ", "target" : "the endpoint: / / client - 05 ed1825 - e70f - 492 - a - af94-03 c633d0affc / 127.0.0.1:2379", "attempt" : 0, "error" : "the RPC error: code = DeadlineExceeded desc = latest balancer error: all SubConns are in TransientFailure, latest connection error: connection closed"} Error: context deadline exceededCopy the code
Solution: Etcdctl requires certificate access
/usr/local/bin/etcdctl --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem put hello world
Copy the code
13.5 You cannot switch between HTTP and HTTPS
Create a cluster using HTTP and then create a cluster using HTTPS.
tls: first record does not look like a TLS handshake
Copy the code
If the cluster is set up successfully, the connection protocol (HTTP/HTTPS) is written to the ETCD store and cannot be changed.
Solution: If you really need to switch the protocol, try the following method
- Delete data: After deleting data, re-establish the cluster
- Do not delete data: You can use snapshot & Restore to perform snapshot and restore operations
13.6 Can apiserver directly use the ETCD certificate generated in Step 5?
After verification, it is possible to use etCD certificates directly, but this is not recommended for production.
In production, you are advised to independently generate certificates for apiserver(or other applications). You can flexibly configure certificates using a generic domain name (*.xx.xx) and different expiration times to facilitate cluster management.