Cluster Maintenance
OS Upgrades
노드 정상적으로 비우기
controlplane ~ ✖ k drain node01 --ignore-daemonsets
node/node01 already cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-86sk5, kube-system/kube-proxy-h5rcc
evicting pod default/blue-6b478c8dbf-qvshb
evicting pod default/blue-6b478c8dbf-74gxg
pod/blue-6b478c8dbf-qvshb evicted
pod/blue-6b478c8dbf-74gxg evicted
node/node01 drained
controlplane ~ ➜ k drain node01 --ignore-daemonsets --force
node/node01 already cordoned
Warning: deleting Pods that declare no controller: default/hr-app; ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-86sk5, kube-system/kube-proxy-h5rcc
evicting pod default/hr-app
pod/hr-app evicted
node/node01 drained
- replicaset이나 deployment로 생성하지 않은 일반 파드는 drain 과정에서 영구적으로 삭제된다. 그러나
--force
옵션을 지정해주면 해당하는 파드 설정 그대로 deployment를 생성해 다른 노드에 파드를 생성할 수 있도록 해줌
Cluster Upgrade Process
노드 버전 확인
controlplane ~ ✖ k get nodes
NAME STATUS ROLES AGE VERSION
controlplane Ready control-plane 41m v1.26.0
node01 Ready <none> 41m v1.26.0
업그레이드 버전 확인
controlplane ~ ➜ kubeadm upgrade plan
~~~
I1221 02:34:51.058481 16023 version.go:256] remote version is much newer: v1.29.0; falling back to: stable-1.26
~~~
Upgrade to the latest version in the v1.26 series:
COMPONENT CURRENT TARGET
kube-apiserver v1.26.0 v1.26.12
kube-controller-manager v1.26.0 v1.26.12
kube-scheduler v1.26.0 v1.26.12
kube-proxy v1.26.0 v1.26.12
CoreDNS v1.9.3 v1.9.3
etcd 3.5.6-0 3.5.6-0
~~~
- remote version은 쿠버네티스 최신 버전
- 그 밑에 1.26 에 해당하는 추천 TARGET 버전
control plane 업그레이드 과정 정리
# plan으로 업그레이드 버전 확인
controlplane ~ ✖ kubeadm upgrade plan
# drain으로 controlplane 비우기
controlplane ~ ➜ k drain controlplane --ignore-daemonsets
node/controlplane cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-7v6dn, kube-system/kube-proxy-sctzx
# apt 업데이트
controlplane ~ ➜ apt update
Get:1 https://packages.cloud.google.com/apt kubernetes-xenial InRelease [8,993 B]
Hit:2 https://download.docker.com/linux/ubuntu focal InRelease
Hit:3 http://security.ubuntu.com/ubuntu focal-security InRelease
Hit:4 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:6 http://archive.ubuntu.com/ubuntu focal-backports InRelease
Fetched 8,993 B in 1s (9,327 B/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
19 packages can be upgraded. Run 'apt list --upgradable' to see them.
# kubeadm 버전 업그레이드
controlplane ~ ➜ apt-get install kubeadm=1.27.0-00
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be upgraded:
kubeadm
1 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.
Need to get 9,931 kB of archives.
After this operation, 1,393 kB of additional disk space will be used.
Get:1 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 kubeadm amd64 1.27.0-00 [9,931 kB]
Fetched 9,931 kB in 0s (31.4 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 20439 files and directories currently installed.)
Preparing to unpack .../kubeadm_1.27.0-00_amd64.deb ...
Unpacking kubeadm (1.27.0-00) over (1.26.0-00) ...
Setting up kubeadm (1.27.0-00) ...
# kubelet 버전 업그레이드
controlplane ~ ➜ apt-get install kubelet=1.27.0-00
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be upgraded:
kubelet
1 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.
Need to get 18.8 MB of archives.
After this operation, 15.1 MB disk space will be freed.
Get:1 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 kubelet amd64 1.27.0-00 [18.8 MB]
Fetched 18.8 MB in 0s (41.6 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 20439 files and directories currently installed.)
Preparing to unpack .../kubelet_1.27.0-00_amd64.deb ...
/usr/sbin/policy-rc.d returned 101, not running 'stop kubelet.service'
Unpacking kubelet (1.27.0-00) over (1.26.0-00) ...
Setting up kubelet (1.27.0-00) ...
/usr/sbin/policy-rc.d returned 101, not running 'start kubelet.service'
# kubectl 버전 업그레이드
controlplane ~ ➜ apt-get install kubectl=1.27.0-00
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be upgraded:
kubectl
1 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.
Need to get 10.2 MB of archives.
After this operation, 1,225 kB of additional disk space will be used.
Get:1 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 kubectl amd64 1.27.0-00 [10.2 MB]
Fetched 10.2 MB in 0s (44.5 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 20439 files and directories currently installed.)
Preparing to unpack .../kubectl_1.27.0-00_amd64.deb ...
Unpacking kubectl (1.27.0-00) over (1.26.0-00) ...
Setting up kubectl (1.27.0-00) ...
# kubeadm upgrade apply로 업그레이드
controlplane ~ ➜ kubeadm upgrade apply v1.27.0
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
~~~
# 데몬 리로드, kubelet 재시작
controlplane ~ ➜ systemctl daemon-reload
controlplane ~ ➜ systemctl restart kubelet
워커 노드 업그레이드
Backup and Restore Methods
사전 작업
# etcdctl 버전 변수로 지정
export ETCDCTL_API=3
# 백업 및 복원 비교를 위한 전체구성 저장
kubectl get all --all-namespaces -o yaml > example.yaml
- etcdctl 명령어 사용 전에 etcd 버전을 3으로 맞춰줘야할 필요가 있음
스냅샷 세이브하기
controlplane ~ ✖ etcdctl snapshot save /opt/snapshot-pre-boot.db --endpoints=127.0.0.1:2379 --key=/etc/kubernetes/pki/etcd/server.key --cert=/etc/kubernetes/pki/etcd/server.crt --cacert=/etc/kubernetes/pki/etcd/ca.crt
Snapshot saved at /opt/snapshot-pre-boot.db
- 스냅샷 세이브 할때는 endpoints, key, cert, cacert를 지정해줘야 정상적으로 저장된다.
- endpoint 주소는
스냅샷 etcdctl 이용해서 복원하기
# snapshot restore 로 dir 복원하기
# etcd snapshot restore --data-dir=<내가 복원하고자 하는 폴더>
# 복원하고자 하는 폴더가 기존에 존재하지 않아야 함.
etcdctl snapshot restore --data-dir=/var/lib/etcd-backup
# etcd static pod의 구성 정보 변경
vi /etc/kubernetes/manifests/etcd.yaml
- hostPath:
# 기존 // path: /var/lib/etcd
path: /var/lib/etcd-backup
type: DirectoryOrCreate
name: etcd-data
- hostPath:name: etcd-data
path: /var/lib/etcd-backup type: DirectoryOrCreate
- 복원 과정은 다른것은 건들 필요 없고 restore 명령어로 폴더 생성해주고, etcd.yaml 파일의 hostPath 위치를 restore 명령어로 만들어진 폴더의 절대 경로로 변경해주면 된다.
Backup and Restore Methods2
클러스터 개수 확인
student-node ~ ✖ k config get-clusters
NAME
cluster1
cluster2
use-context를 이용해 다른 클러스터로 이동
student-node ~ ➜ k config use-context cluster1
Switched to context "cluster1".
외부 etcd 서버에 접근하기
# 외부 etcd 서버가 구성되어 있는 클러스터로 접근해서 ssh etcd-server 명령어 수행
student-node ~ ➜ ssh etcd-server
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1106-gcp x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
Last login: Fri Dec 22 06:15:54 2023 from 192.8.70.12
# 외부 etcd ip를 확인 후 해당 ip로 ssh 접근
student-node ~ ➜ ssh 192.8.70.6
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1106-gcp x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
외부 etcd data-dir 확인하는 법
# etcd는 프로세스로 올라와 있기 때문에 ps 명령어와 grep을 이용해 data-dir 부분을 확인해주면 된다.
etcd-server /var/lib/etcd-data ➜ ps -ef | grep etcd
etcd 819 1 0 05:11 ? 00:00:58 /usr/local/bin/etcd --name etcd-server --data-dir=/var/lib/etcd-data --cert-file=/etc/etcd/pki/etcd.pem --key-file=/etc/etcd/pki/etcd-key.pem --peer-cert-file=/etc/etcd/pki/etcd.pem --peer-key-file=/etc/etcd/pki/etcd-key.pem --trusted-ca-file=/etc/etcd/pki/ca.pem --peer-trusted-ca-file=/etc/etcd/pki/ca.pem --peer-client-cert-auth --client-cert-auth --initial-advertise-peer-urls https://192.8.70.6:2380 --listen-peer-urls https://192.8.70.6:2380 --advertise-client-urls https://192.8.70.6:2379 --listen-client-urls https://192.8.70.6:2379,https://127.0.0.1:2379 --initial-cluster-token etcd-cluster-1 --initial-cluster etcd-server=https://192.8.70.6:2380 --initial-cluster-state new
root 1973 1229 0 06:18 pts/0 00:00:00 grep etcd
- Stacked etcd 와 External etcd 라는 개념이 있음
- Stacked 는 컨트롤 플레인 내부에서 다른 컴포넌트와 통신하는 etcd
- External 는 컨트롤 플레인 내부가 아닌 외부에 다른 노드에 구성된 etcd, External 인지 확인하는 방법은 kube-apiserver의 etcd 설정이 어떻게 되어 있는지 확인하는 방법과 컨트롤 플레인의 pod를 체크하는 방법이 있음 (ip가 172로 시작하는 로컬 호스트 주소가 아니라면 external이다.)
- Stacked 는 컨트롤 플레인 내부에서 다른 컴포넌트와 통신하는 etcd
etcd 데이터 직접 확인하는 법
etcd-server /var/lib/etcd-data ➜ ETCDCTL_API=3 etcdctl \
> --endpoints=https://127.0.0.1:2379 \
> --cacert=/etc/etcd/pki/ca.pem \
> --cert=/etc/etcd/pki/etcd.pem \
> --key=/etc/etcd/pki/etcd-key.pem \
> member list
840c04836d906824, started, etcd-server, https://192.8.70.6:2380, https://192.8.70.6:2379, false
etcd-server /var/lib/etcd-data ➜ ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/pki/ca.pem --cert=/etc/etcd/pki/etcd.pem --key=/etc/etcd/pki/etcd-key.pem member
NAME:
member - Membership related commands
USAGE:
etcdctl member <subcommand> [flags]
API VERSION:
3.4
COMMANDS:
add Adds a member into the cluster
list Lists all members in the cluster
promote Promotes a non-voting member in the cluster
remove Removes a member from the cluster
update Updates a member in the cluster
- endpoints, cacert, cert, key를 지정해주고 member list 해주면 된다.
- 이건 사실 정확히 모르겠음 조금 더 찾아봐야할 듯
- 대략 유추 해보면 etcd-server에 데이터를 직접 확인하는 것으로 보임
- 궁금해서 찾아보니 etcdctl 내에 member라는 명령어가 있고, 여러가지 서브 커맨드가 있음
context 외부에 있는 etcd 백업 후 복사하는 과정
# 외부에 있는 서버로 접근
ssh cluster1-controlplane
# 외부 서버에서 etcd snapshot
cluster1-controlplane ~ ✖ ETCDCTL_API=3 etcdctl snapshot save --key=/etc/kubernetes/pki/etcd/server.key --cert=/etc/kubernetes/pki/etcd/server.crt --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 ~/cluster1.db
Snapshot saved at /root/cluster1.db
cluster1-controlplane ~ ➜ exit
logout
# student-node 라는 원 서버 돌아와서 scp로 백업 파일 복사
# 왜 이렇게 했냐면 student-node라는 서버는 ssh 인증이 되어 있기 때문 그 외 cluster -> student로는 ssh 통신이 안되는 상황
student-node ~ ➜ scp cluster1-controlplane:~/cluster1.db /opt/cluster1.db
cluster1.db 100% 2012KB 91.8MB/s 00:00
External ETCD restore 하는 과정
# 백업 파일 준비해서 scp 이용해 restore 하고자 하는 노드로 전송
student-node ~ scp /opt/cluster2.db etcd-server:~/
# external etcd server로 이동
student-node ~ ssh etcd-server
# 서버 안에서 restore
# key, cert, cacert, endpoints 지정해서 restore
etcd-server ~ ➜ ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/pki/ca.pem --cert=/etc/etcd/pki/etcd.pem --key=/etc/etcd/pki/etcd-key.pem snapshot restore /root/cluster2.db --data-dir /var/lib/etcd-data-new
{"level":"info","ts":1662004927.2399247,"caller":"snapshot/v3_snapshot.go:296","msg":"restoring snapshot","path":"/root/cluster2.db","wal-dir":"/var/lib/etcd-data-new/member/wal","data-dir":"/var/lib/etcd-data-new","snap-dir":"/var/lib/etcd-data-new/member/snap"}
{"level":"info","ts":1662004927.2584803,"caller":"membership/cluster.go:392","msg":"added member","cluster-id":"cdf818194e3a8c32","local-member-id":"0","added-peer-id":"8e9e05c52164694d","added-peer-peer-urls":["http://localhost:2380"]}
{"level":"info","ts":1662004927.264258,"caller":"snapshot/v3_snapshot.go:309","msg":"restored snapshot","path":"/root/cluster2.db","wal-dir":"/var/lib/etcd-data-new/member/wal","data-dir":"/var/lib/etcd-data-new","snap-dir":"/var/lib/etcd-data-new/member/snap"}
# 폴더 소유 권한 수정 후 확인
etcd-server ~ ✖ chown -R etcd:etcd /var/lib/etcd-data-new
etcd-server ~ ➜ ls -ld /var/lib/etcd-data-new
drwx------ 3 etcd etcd 4096 Jan 2 03:57 /var/lib/etcd-data-new
# etcd 서버의 서비스 파일 수정
etcd-server ~ ➜ systemctl status etcd
etcd.service - etcd key-value store
Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-12-22 07:36:56 UTC; 5min ago
Docs: https://github.com/etcd-io/etcd
Main PID: 3360 (etcd)
Tasks: 43 (limit: 251379)
# service 파일 수정
etcd-server ~ ✖ vi /etc/systemd/system/etcd.service
# data-dir 파일을 restore 한 디렉터리로 지정
[Service]
User=etcd
Type=notify
ExecStart=/usr/local/bin/etcd \
--name etcd-server \
--data-dir=/var/lib/etcd-data-new \
--cert-file=/etc/etcd/pki/etcd.pem \
# 데몬 및 서비스 리스타트
etcd-server ~ ➜ systemctl daemon-reload
etcd-server ~ ➜ systemctl restart etcd
- chown 이용해서 권한 수정하는 경우 -R 옵션을 빼놓지 않아야 한다.
Security
View Certificate Details
Common Name (CN) 확인 법
openssl x509 -in <cert file path> -text -noout
- Issuer : 인증서를 발급한 사람, 발행자
- Subject : 인증서를 발급받은 사람, 소유자
- X509v3 Subject Alternative Name 항목을 확인하면 AN 확인 가능
- 주로 인증서에 대해 분석하고 확인하는 데 중점을 두면 될듯.
- api-server manifest 파일에 etcd 설정 시 api-server의 ca 파일이 아니라 etcd의 ca 파일이어야 함
- 보통 CN을 많이 물어볼 것 같은데 CN이라 함은 Subject 의 CN을 확인하면 된다.
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- kubeapi server의 환경설정에서 etcd-cafile 은 /pki 경로에 있는 ca 파일이 아니라 /pki/etcd/ 경로에 있는 파일임
Certificates API
CSR 생성하는 법
jane.csr
--- BEGIN ~~~ ---
MIROSLFKWENFKLASNVOWN ~~~
--- END ~~ ---
# csr 파일 내용을 base64로 다시 인코딩
cat jane.csr | base64 | tr -d "\n"
LS0tLS1CRUd~~~~
# 해당 파일을 CSR 파일 내용에 포함
jane-csr.yaml
---
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: jane
spec:
groups:
- system:authenticated
usages:
- digital signature
- key encipherment
- server auth
request:
LS0tLS1CRUd~~~~
CSR 승인하는 법
kubectl certificate approve <CSR Name>
CSR 요청 확인, 거부, 삭제하는 법
# 확인
controlplane ~ ✖ k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
agent-smith 114s kubernetes.io/kube-apiserver-client agent-x <none> Denied
akshay 4m53s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Approved,Issued
csr-stg9s 15m kubernetes.io/kube-apiserver-client-kubelet system:node:controlplane <none> Approved,Issued
# 거부
controlplane ~ ➜ kubectl certificate deny agent-smith
certificatesigningrequest.certificates.k8s.io/agent-smith denied
# 삭제
controlplane ~ ➜ k delete csr agent-smith
certificatesigningrequest.certificates.k8s.io "agent-smith" deleted
KubeConfig
기본 kubeconfig 위치
/root/.kube/config
context 특정 파일 이용해서 변경
controlplane ~/.kube ➜ kubectl config --kubeconfig=/root/my-kube-config use-context research
Switched to context "research".
kubeconfig yaml 파일
users:
- name: aws-user
user:
client-certificate: /etc/kubernetes/pki/users/aws-user/aws-user.crt
client-key: /etc/kubernetes/pki/users/aws-user/aws-user.key
- name: dev-user
user:
client-certificate: /etc/kubernetes/pki/users/dev-user/developer-user.crt
client-key: /etc/kubernetes/pki/users/dev-user/dev-user.key
- name: test-user
user:
client-certificate: /etc/kubernetes/pki/users/test-user/test-user.crt
client-key: /etc/kubernetes/pki/users/test-user/test-user.key
인증 관련 문제로 출력되지 않는 에러
controlplane ~/.kube ➜ k get pods
error: unable to read client-cert /etc/kubernetes/pki/users/dev-user/developer-user.crt for dev-user due to open /etc/kubernetes/pki/users/dev-user/developer-user.crt: no such file or directory
- config 파일에서 user의 경우 crt 파일이나 key 파일이 일치하지 않으면 문제가 발생한다. 만약 위와 같은 로그가 발생 시 인증서나 key를 확인하는 것도 필요할듯
Role Based Access Controls
확인 명령어
# api server authorization mode 확인
controlplane ~ ➜ k get po -n kube-system kube-apiserver-controlplane -o yaml
- --authorization-mode=Node,RBAC
# role 확인 명령어
controlplane ~ ✖ k get role
No resources found in default namespace.
# 아래와 같이 확인하면 리소스와 어떤 action 가능한지도 있음
controlplane ~ ➜ k get role -n kube-system kube-proxy -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: "2023-12-27T08:12:47Z"
name: kube-proxy
namespace: kube-system
resourceVersion: "284"
uid: c6de2a17-a497-41eb-b97b-362457caf43b
rules:
- apiGroups:
- ""
resourceNames:
- kube-proxy
resources:
- configmaps
verbs:
- get
# 아래와 같이 확인하면 어떤 롤이 어떤 개체에 바인딩 되어 있는지 확인 가능
controlplane ~ ➜ k get rolebinding -n kube-system kube-proxy -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: "2023-12-27T12:26:02Z"
name: kube-proxy
namespace: kube-system
resourceVersion: "292"
uid: f3334052-d107-46d8-8d6c-fdd3d88b4486
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kube-proxy
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:bootstrappers:kubeadm:default-node-token
# 특정 유저의 Role로 Action 실행하기
controlplane ~ ➜ k get po --as dev-user # --as 옵션을 이용해서 특정 user로 명령어를 실행할 수 있다.
Error from server (Forbidden): pods is forbidden: User "dev-user" cannot list resource "pods" in API group "" in the namespace "default"
# Role과 RoleBinding 생성하기
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: developer
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "create","delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dev-user-binding
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
명령형으로 Role 과 RoleBinding 만들기
controlplane ~ ✖ k create role developer --verb list,create,delete --resource pods -o yaml --dry-run=client > role.yaml
controlplane ~ ➜ k create rolebinding dev-user-binding --role developer --user dev-user --dry-run=client -o yaml > rb.yaml
Cluster Roles
Get
controlplane ~ ✖ k get clusterrole
controlplane ~ ➜ k get clusterrolebindings.rbac.authorization.k8s.io
명령형으로 생성하기
controlplane ~ ✖ k create clusterrole node-admin --resource node --verb list,get,watch,delete,create
clusterrole.rbac.authorization.k8s.io/node-admin created
controlplane ~ ➜ k create clusterrolebinding michelle-binding --user michelle --clusterrole node-admin
clusterrolebinding.rbac.authorization.k8s.io/michelle-binding created
Storage role 생성하기
controlplane ~ ➜ k create clusterrole storage-admin --resource persistentvolumes,storageclasses --verb create,list,get,watch,delete
clusterrole.rbac.authorization.k8s.io/storage-admin created
controlplane ~ ➜ k create clusterrolebinding michelle-storage-admin --clusterrole storage-admin --user michelle
clusterrolebinding.rbac.authorization.k8s.io/michelle-storage-admin created
- 리소스를 다중으로 적고 생성하게 되면 모든 리소스에 대한 verb가 생성됨
Service Accounts
확인 명령어
controlplane ~ ➜ k get sa default -o yaml
파드에서 사용중인 serviceAccount 관련 정보 확인
controlplane ~ ➜ k get po web-dashboard-97c9c59f6-9gjzx -o yaml
~~~
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-c9b9c
readOnly: true
~~~
spec:
serviceAccountName: default
~~~
생성
controlplane ~ ➜ k create sa dashboard-sa
serviceaccount/dashboard-sa created
deployment에 serviceAccount 설정
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: web-dashboard
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
name: web-dashboard
spec:
serviceAccountName: dashboard-sa
containers:
- serviceAccountName 항목을 ..template.spec 밑에 작성해주면 된다.
Image Security
docker registry 관련 secret 생성
root@controlplane ~ ➜ k create secret docker-registry private-reg-cred --docker-username=dock_user --docker-password=dock_password --docker-server=myprivateregistry.com:5000 --docker-email=dock_user@myprivateregistry.com
secret/private-reg-cred created
deployment에서 private registry 이용하기
~~~
template:
metadata:
labels:
app: web
spec:
imagePullSecrets:
- name: private-reg-cred
~~~
Security Contexts
명령어 특정 User로 실행하기
---
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
namespace: default
spec:
securityContext:
runAsUser: 1010
containers:
- command:
- sleep
- "4800"
image: ubuntu
name: ubuntu-sleeper
- spec.securityContext.runAsUser 항목에 원하는 유저의 ID를 적어주면된다.
apiVersion: v1
kind: Pod
metadata:
name: multi-pod
spec:
securityContext:
runAsUser: 1001
containers:
- image: ubuntu
name: web
command: ["sleep", "5000"]
securityContext:
runAsUser: 1002
- image: ubuntu
name: sidecar
command: ["sleep", "5000"]
- 만약 멀티 컨테이너 파드의 경우 컨테이너 안에 있는 securityContext가 우선시 됨
- 위의 예로는 web 컨테이너는 1002 User, sidecar 컨테이너는 1001 User
spec:
containers:
- command:
- sleep
- "4800"
image: ubuntu
name: ubuntu
securityContext:
capabilities:
add: ["SYS_TIME"]
nodeName: controlplane
- capabilities를 추가하고자 하면 add: [list] 로 추가하면 된다. 다중으로 추가하는 경우 add: ["NET_ADMIN", "SYS_TIME"] 이렇게 추가하면 됨
- spec 밑에 두는 securityContext와 container 밑에 두는 securityContext를 잘 구분해야할듯
Network Policies
Yaml 예시
name: internal-policy
namespace: default
spec:
egress:
- to:
- podSelector:
matchLabels:
name: payroll
ports:
- port: 8080
protocol: TCP
- to:
- podSelector:
matchLabels:
name: mysql
ports:
- port: 3306
protocol: TCP
podSelector:
matchLabels:
name: internal
policyTypes:
- Egress
- spec.egress 밑에 to 를 두거나 spec.ingress 밑에 from을 두어서 ingress 또는 egress 트래픽을 허용해줄수 있다.
- 주의해야할 점은 ingress와 egress를 동시에 허용해주려면 policyTypes에 Ingress와 Egress를 모두 기재해주어야 함
다중 포트 예시
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
namespace: default
name: internal-policy
spec:
ingress:
- from:
- podSelector:
matchLabels:
name: internal
ports:
- port: 8080
protocol: TCP
podSelector:
matchLabels:
name: payroll
egress:
- to:
- podSelector:
matchLabels:
name: payroll
ports:
- port: 8080
protocol: TCP
- to:
- podSelector:
matchLabels:
name: mysql
ports:
- port: 3306
protocol: TCP
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
policyTypes:
- Ingress
- Egress
- spec.egress[] to 부분을 보면 to를 여러 개 설정해 각기 다른 egress 정책을 설정 가능함.
- 다른 파드 셀렉터에 다른 포트를 지정하는 경우 유용할 듯하다. (AWS SG의 하나의 규칙이 to 라고 봐도 될듯함)
- 그리고 spec.egress[] 에서 ports 부분을 보면 달랑 포트만 설정되어 있는 것을 볼 수 있는데 이는 해당 포트에 대한 egress를 모두 허용한다는 이야기
Storage
Persistent Volume Claims
spec:
containers:
- name: event-simulator
image: kodekloud/event-simulator
env:
- name: LOG_HANDLERS
value: file
volumeMounts:
- mountPath: /log
name: log-volume
volumes:
- name: log-volume
hostPath:
# directory location on host
path: /var/log/webapp
# this field is optional
type: Directory
- 컨테이너 내부의 path를 hostPath를 이용해서 로컬 호스트의 볼륨을 사용할 수 있게 함
pv 생성 예시
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-log
spec:
persistentVolumeReclaimPolicy: Retain
accessModes:
- ReadWriteMany
capacity:
storage: 100Mi
hostPath:
path: /pv/log
PVC Yaml 예시
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim-log-1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
파드에 PVC 할당 예시
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: event-simulator
image: kodekloud/event-simulator
env:
- name: LOG_HANDLERS
value: file
volumeMounts:
- mountPath: /log
name: log-volume
volumes:
- name: log-volume
persistentVolumeClaim:
claimName: claim-log-1
pvc 삭제
controlplane ~ ➜ k delete pvc claim-log-1
persistentvolumeclaim "claim-log-1" deleted
- pod에서 pvc를 사용중일 때에는 삭제되지 않고 hang 상태에 걸리며 pvc는 terminating 상태로 고정된다.
Storage Class
storageclass 확인
controlplane ~ ➜ k get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 9m23s
local-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 5s
portworx-io-priority-high kubernetes.io/portworx-volume Delete Immediate false 5s
- 만약 PROVISIONER가 no-provisioner일 경우 동적 프로비저닝 되지 않는 local 볼륨이다.
스토리지 클래스 Yaml 예시
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: delayed-volume-sc
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
- 이 섹션은 스토리지 클래스에 대한 이해 문제가 많은듯
Networking
Explore Environment
ip 인터페이스 확인하기
controlplane ~ ➜ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN group default
link/ether 62:fd:46:a6:e3:38 brd ff:ff:ff:ff:ff:ff
inet 10.244.0.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
3: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default qlen 1000
link/ether 9e:81:1e:b4:0c:31 brd ff:ff:ff:ff:ff:ff
inet 10.244.0.1/24 brd 10.244.0.255 scope global cni0
valid_lft forever preferred_lft forever
4: veth9ff14959@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue master cni0 state UP group default
link/ether 42:25:e2:1e:c8:84 brd ff:ff:ff:ff:ff:ff link-netns cni-deee82e4-8832-478d-1ed6-0ec4a3c1e4df
5: veth425d657c@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue master cni0 state UP group default
link/ether 2e:5c:20:f1:42:b7 brd ff:ff:ff:ff:ff:ff link-netns cni-38f750b4-0253-1759-7c69-fff870be0128
4246: eth0@if4247: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:c0:10:80:0c brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.16.128.12/24 brd 192.16.128.255 scope global eth0
valid_lft forever preferred_lft forever
4248: eth1@if4249: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:19:00:2a brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 172.25.0.42/24 brd 172.25.0.255 scope global eth1
valid_lft forever preferred_lft forever
controlplane ~ ➜ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 62:fd:46:a6:e3:38 brd ff:ff:ff:ff:ff:ff
3: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 9e:81:1e:b4:0c:31 brd ff:ff:ff:ff:ff:ff
4: veth9ff14959@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue master cni0 state UP mode DEFAULT group default
link/ether 42:25:e2:1e:c8:84 brd ff:ff:ff:ff:ff:ff link-netns cni-deee82e4-8832-478d-1ed6-0ec4a3c1e4df
5: veth425d657c@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue master cni0 state UP mode DEFAULT group default
link/ether 2e:5c:20:f1:42:b7 brd ff:ff:ff:ff:ff:ff link-netns cni-38f750b4-0253-1759-7c69-fff870be0128
4246: eth0@if4247: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:c0:10:80:0c brd ff:ff:ff:ff:ff:ff link-netnsid 0
4248: eth1@if4249: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:ac:19:00:2a brd ff:ff:ff:ff:ff:ff link-netnsid 1
- ip link 명령어는 아이피는 나오지 않으니 ip a를 통해 확인하면 될듯?
브릿지 확인하는 법
controlplane ~ ✖ ip link show type bridge
3: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 9e:81:1e:b4:0c:31 brd ff:ff:ff:ff:ff:ff
CNI
kubelet endpoint 확인하는 법
controlplane ~ ➜ ps -ef | grep kubelet
root 4689 1 0 07:25 ? 00:00:04 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9
cni 지원 플러그인 확인
controlplane ~ ➜ ls /opt/cni/bin
bandwidth dhcp firewall host-device ipvlan macvlan ptp static vlan
bridge dummy flannel host-local loopback portmap sbr tuning vrf
cni에서 설치되지 않은 플러그인 찾기
controlplane ~ ➜ ls -l /opt/cni/bin | grep -E "vlan|bridge|dhcp|cisco"
-rwxr-xr-x 1 root root 4299004 Jan 16 2023 bridge
-rwxr-xr-x 1 root root 10167415 Jan 16 2023 dhcp
-rwxr-xr-x 1 root root 3999593 Jan 16 2023 ipvlan
-rwxr-xr-x 1 root root 4029261 Jan 16 2023 macvlan
-rwxr-xr-x 1 root root 3993252 Jan 16 2023 vlan
- 반대로 생각하면 /opt/cni/bin 에 있는 플러그인은 모두 설치된 플러그인
현재 cni에서 사용중인 plugin 확인하기
controlplane ~ ➜ ls /etc/cni/net.d
10-flannel.conflist
Deploy Network Solution
weave plugin daemonset 설치
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
Networking Weave
현재 사용하고 있는 cni 확인
controlplane ~ ➜ ls /etc/cni/net.d/
10-weave.conflist
weave agent/peers 개수 확인하기
controlplane ~ ✖ k get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-5d78c9869d-nbv9t 1/1 Running 0 69m
kube-system coredns-5d78c9869d-vmd9p 1/1 Running 0 69m
kube-system etcd-controlplane 1/1 Running 0 69m
kube-system kube-apiserver-controlplane 1/1 Running 0 69m
kube-system kube-controller-manager-controlplane 1/1 Running 0 69m
kube-system kube-proxy-2vchc 1/1 Running 0 69m
kube-system kube-proxy-pxp5g 1/1 Running 0 69m
kube-system kube-scheduler-controlplane 1/1 Running 0 69m
kube-system weave-net-b5ddf 2/2 Running 0 69m
kube-system weave-net-s8hcr 2/2 Running 1 (69m ago) 69m
- weave-net 이름이 붙은 파드를 확인하면 된다.
bridge 타입의 리소스 확인 (weave가 생성한 bridge를 확인할때)
controlplane ~ ✖ ip link show type bridge
4: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether ce:3a:ac:d2:fa:17 brd ff:ff:ff:ff:ff:ff
weave에서 설정한 Pod IP 주소 범위는?
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: IPALLOC_RANGE
value: 10.244.0.0/16
- IPALLOC_RANGE 범위를 참고하면 된다.
특정 노드 default gateway 확인하는 법
controlplane ~ ✖ k run po --dry-run=client --image=busybox -o yaml temp > temp.yaml
controlplane ~ ➜ vi temp.yaml
controlplane ~ ➜ k apply -f temp.yaml
pod/temp created
controlplane ~ ➜ k exec temp -- ip route
default via 10.244.192.0 dev eth0
10.244.0.0/16 dev eth0 scope link src 10.244.192.1
controlplane ~ ➜ ssh node01
root@node01 ~ ➜ ip route
default via 172.25.0.1 dev eth1
10.244.0.0/16 dev weave proto kernel scope link src 10.244.192.0
172.25.0.0/24 dev eth1 proto kernel scope link src 172.25.0.60
192.12.183.0/24 dev eth0 proto kernel scope link src 192.12.183.6
- 두 가지 방법이 있음 , busybox로 nodeName 이용해서 특정 노드에 파드 생성해준 뒤 ip route 명령어를 이용해서 나오는 default 주소를 확인하거나
- ssh node01로 이동해서 ip route를 입력해 나오는 weave의 src 주소를 확인
Service Networking
node의 ip 범위 확인
controlplane ~ ➜ ip addr | grep eth0
4360: eth0@if4361: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
inet 192.13.147.9/24 brd 192.13.147.255 scope global eth0
- inet 뒤의 192.13.147.9/24 주소를 확인하면 프리픽스가 24인 것을 확인 가능
pod의 ip 범위 확인
controlplane ~ ➜ ip addr | grep weave
4: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP group default qlen 1000
inet 10.244.0.1/16 brd 10.244.255.255 scope global weave
7: vethwe-bridge@vethwe-datapath: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue master weave state UP group default
10: vethwepl7bf057a@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue master weave state UP group default
12: vethwepl06582fa@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue master weave state UP group default
- pod의 범위 확인은 cni의 inet 10.244.0.1/16 주소를 확인하면 됨
서비스의 ip 범위 확인
controlplane ~ ➜ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep cluster-ip-range
- --service-cluster-ip-range=10.96.0.0/12
- kube-apiser yaml 파일에서 service-cluster-ip-range 항목이 서비스의 ip 범위이다.
CoreDNS in Kubernetes
사용중인 DNS 솔루션 확인
controlplane ~ ➜ k get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5d78c9869d-jpc8g 1/1 Running 0 118s
coredns-5d78c9869d-xn6cl 1/1 Running 0 118s
etcd-controlplane 1/1 Running 0 2m14s
kube-apiserver-controlplane 1/1 Running 0 2m14s
kube-controller-manager-controlplane 1/1 Running 0 2m10s
kube-proxy-ct69c 1/1 Running 0 118s
kube-scheduler-controlplane 1/1 Running 0 2m10s
- kube-system 네임스페이스에 있는 파드를 확인하면 된다. 보통 DNS 솔루션은 kube-system 에 있음
사용중인 DNS 솔루션의 서비스 네임 확인
controlplane ~ ➜ k get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 3m16s
- 보통 CoreDNS를 설치하면 kube-dns라는 이름으로 서비스가 생성된다.
CoreDNS 서비스의 config 파일 확인
controlplane ~ ➜ ps -ef | grep core
root 6544 6419 0 05:54 ? 00:00:00 /coredns -conf /etc/coredns/Corefile
root 7070 6900 0 05:54 ? 00:00:00 /coredns -conf /etc/coredns/Corefile
root 10383 8159 0 05:59 pts/0 00:00:00 grep --color=auto core
- 프로세스에서 core를 검색해보면 coredns -conf 인자 값으로 Corefile이라는 이름으로 config 파일이 구성되어 있는 것을 알 수 있음
Corefile이 CoreDNS Pod로 어떻게 주입되는지 확인
controlplane ~ ➜ k get po -n kube-system coredns-5d78c9869d-jpc8g -o yaml
apiVersion: v1
~~~
volumes:
- configMap:
defaultMode: 420
items:
- key: Corefile
path: Corefile
name: coredns
name: config-volume
- configMap의 형태로 volumeMount 되어 파드에 제공된다.
CoreDNS의 root domain 확인
controlplane ~ ➜ k get cm -n kube-system -o yaml coredns
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2024-01-09T10:53:48Z"
name: coredns
namespace: kube-system
resourceVersion: "275"
uid: 7db77577-2087-498d-9d1f-fad73b0d0bb9
- data 항목에서 Corefile 항목을 확인하면 kubernetes 다음에 있는 cluster.local이 root domain이다. 해당 자리에 오는 도메인이 루트 도메인
CKA - Ingress Networking - 1
ingress resource 확인하기
controlplane ~ ➜ k get ingress -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
app-space ingress-wear-watch <none> * 10.105.9.73 80 99s
CKA - Ingress Networking - 2
Install
Cluster Installation using Kubeadm
Troubleshooting
Application Failure
주로 Selector나 deployment 등 2-Tier 구조에서 애플리케이션의 문제를 해결하는 문제가 많이 나왔음
문제 유형으로는
- 디플로이먼트의 포트가 상이함
- 셀렉터의 레이블이 일치하지 않음
- env에 있는 DB 호스트 정보가 실제로 구동중인 DB Pod와 일치하지 않음
- env에 있는 DB User 정보가 구동중인 DB Pod와 일치하지 않음
- User를 root로 변경하니 정상 처리 됨
- 노드 포트의 포트 번호가 문제와 상이함
Control Plane Failure
문제 유형
- scheduler의 Exec 명령어 부분이 이상해서 고쳐 주었음. 밑에는 그 에러로그임
exec: "kube-schedulerrrr": executable file not found in $PATH: unknown'
- controller manager의 kubeconfig 옵션이 이상하게 설정 되어 있었음. 원래 대로인 controller-manager.conf 로 변경 해주었음.
--kubeconfig=/etc/kubernetes/controller-manager-XXXX.conf
- controller가 고장나 있었음. 로그를 체크 해보니 ca.crt 파일이 없다고 함. 그래서 yaml 파일을 살펴보다 hostPath가 잘못되어 있는것 발견해 고쳐주었음
controlplane /etc/kubernetes ✖ k logs -n kube-system kube-controller-manager-controlplane I0112 05:55:47.202450 1 serving.go:348] Generated self-signed cert in-memory E0112 05:55:47.415001 1 run.go:74] "command failed" err="unable to load client CA provider: open /etc/kubernetes/pki/ca.crt: no such file or directory"
hostPath:
path: /etc/kubernetes/WRONG-PKI-DIRECTORY type: DirectoryOrCreate`
Worker Node Failure
문제 유형
- node 가 notReady 상태였음. ssh node01 해서 확인 해보니 kubelet 서비스가 정상작동 중이지 않은 것을 보았고, systemctl restart kubelet으로 해결해주었음
- kubelet 에서 문제가 발생해서 뜨지 않았음. journalctl 명령어 이용해서 어떤 문제가 발생 중인지 확인해줌. unable ca 파일이라고 하고 기존에 쿠버네티스는 ca.crt 파일을 ca 파일로 사용함.
Jan 12 02:07:30 node01 kubelet[11794]: E0112 02:07:30.118703 11794 run.go:74] "command failed" err="failed to construct kubelet dependencies: unable to load client CA file /etc/kubernetes/pki/kubelet.crt: open /etc/kubernetes/pki/kubelet.crt: no such file or directory"`
- config를 변경해줌
# root@node01 /var/lib/kubelet ➜ vi /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1 authentication: anonymous: enabled: false webhook: cacheTTL: 0s enabled: true x509: clientCAFile: /etc/kubernetes/pki/ca.crt authorization: mode: Webhook webhook: cacheAuthorizedTTL: 0s cacheUnauthorizedTTL: 0s cgroupDriver: systemd
- node01이 또 문제가 발생해서 journalctl 명령어 이용해서 로그 확인함
Jan 12 02:32:04 node01 kubelet[15161]: E0112 02:32:04.637367 15161 kubelet_node_status.go:92] "Unable to register node with API server" err="Post \"https://controlplane:6553/api/v1/nodes\": dial tcp 192.12.45.9:6553: connect: connection refused" node="node01"
- 해당 로그 확인 후 포트가 잘못되어 있어 포트를 6443으로 변경함
server: https://controlplane:6443
name: default-cluster
contexts:
context:
cluster: default-cluster
namespace: default
user: default-auth
name: default-context
Troubleshoot Network
- kube-proxy 문제가 발생함.
root@controlplane /etc/cni/net.d ✖ k logs -n kube-system kube-proxy-z4fxm
E0112 07:44:43.667574 1 run.go:74] "command failed" err="failed complete: open /var/lib/kube-proxy/configuration.conf: no such file or directory"
- 로그 체크하고 configuration.conf 가 아니라 config.conf 파일로 변경해주어야함 k edit 명령어 이용해서 변경해주었음
# root@controlplane /var/lib/kubelet ➜ k edit ds -n kube-system kube-proxy
containers:
- command:
- /usr/local/bin/kube-proxy
- --config=/var/lib/kube-proxy/config.conf
- --hostname-override=$(NODE\_NAME)
Other Topics
JSON PATH
기본적인 출력
controlplane ~ ✖ k get nodes -o jsonpath='{.items\[_\].metadata.name}{.items\[_\].status.capacity.cpu}'
controlplane node0136 36
controlplane ~ ✖ k get nodes -o jsonpath='{.items\[_\].metadata.name}{"\\t"}{.items\[_\].status.capacity.cpu}'
controlplane node01 36 36
controlplane ~ ✖ k get nodes -o jsonpath='{.items\[_\].metadata.name}{"\\n"}{.items\[_\].status.capacity.cpu}'
controlplane node01
36 36
controlplane ~ ✖ k get nodes -o jsonpath='{range .items\[\*\]}{.metadata.name}{"\\t"}{.status.capacity.cpu}{"\\n"}{end}'
controlplane 36
node01 36
- range end를 이용해서 loop를 돌릴수도 있음
controlplane ~ ✖ k get nodes -o custom-columns=NODE:.metadata.name,CPU:.status.capacity.cpu
NODE CPU
controlplane 36
node01 36
- custom-columns를 이용해서 원하는 커스텀 컬럼과 데이터를 매칭할 수도 있음
**kubeconfig 파일 지정해서 config로 출력하기**
controlplane ~ ✖ kubectl config view --kubeconfig=/root/my-kube-config
controlplane ~ ➜ kubectl config view --kubeconfig=/root/my-kube-config -o jsonpath='{.users[*].name}'
aws-user dev-user test-user
**sort-by로 정렬**
controlplane ~ ✖ k get pv --sort-by=spec.capacity.storage -o custom-columns='NAME:metadata.name','CAPACITY:spec.capacity.storage'
NAME CAPACITY
pv-log-4 40Mi
pv-log-1 100Mi
pv-log-2 200Mi
pv-log-3 300Mi
- `--sort-by`로 정렬 한뒤 `-o custom-columns='<column name>:<data name>'` 이걸로 원하는 커스텀 컬럼과 데이터 매핑 가능
**특정 데이터 기준으로 sort하는 법**
kubectl get pv --sort-by=.spec.capacity.storage > /opt/outputs/storage-capacity-sorted.txt
value 기반으로 데이터 찾기
kubectl config view --kubeconfig=my-kube-config -o jsonpath="{.contexts[?(@.context.user=='aws-user')].name}" > /opt/outputs/aws-context-name
```
Advanced Kubectl Commands
'자격증 > Kubernetes CKA' 카테고리의 다른 글
[CKA] 자격증 합격 후기 (0) | 2024.01.14 |
---|---|
[CKA] 명령어 정리 - 1 (1) | 2024.01.02 |
[CKA] Practice Test - Env Variables (0) | 2024.01.01 |
[CKA] Practice Test - Commands And Arguments (1) | 2024.01.01 |
[CKA] Troubleshooting (0) | 2023.12.31 |