3. Container/Kubernetes
- centos7에서 docker 설치
- container에서 the input device is not a TTY 로그 출력시 조치
- docker 와 cri-o 비교
- Docker컨테이너 저장경로 변경방법
- k8s 강제로 pod 종료시키는 방법
- kubernetes-Istio구성정보
- podman기반의 컨테이너 정보 설정
- Podman기반의 DNS연동
- podman사용하기
- podman에서 컨테이너가 실행되지 않을때 조치방법
- etcd의 member확인
- kubeadm 노드추가
- etcd member 제외 방법
- 컨테이너 구동시 unknown server host 메시지 뜨면서 구동실패
- pod 구동될때 Imageinspecterror or readlink invalid argument error 메시지 발생
- 워커노드 제외방법
- 특정 노드에만 배포할 수 있는 taint 설정하기
centos7에서 docker 설치
- yum 리포지터리 추가
$> wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker.repo $> yum install docker-ce -y
- docker서비스 활성화 후 시작
$> systemctl enable docker --now
- Docker 정보 확인
$> docker info docker info Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Build with BuildKit (Docker Inc., v0.5.0-docker) Server: Containers: 10 Running: 10 Paused: 0 Stopped: 0 Images: 17 Server Version: 20.10.1 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc Default Runtime: runc Init Binary: docker-init containerd version: 269548fa27e0089a8b8278fc4fc781d7f65a939b runc version: ff819c7e9184c13b7c2607fe6c30ae19403a7aff init version: de40ad0 Security Options: seccomp Profile: default Kernel Version: 3.10.0-1160.6.1.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 15.42GiB Name: test.co.kr ID: YDW3:HAGH:ZX2W:WBP4:US75:UK3H:A55N:M2CG:D7A7:5Q5Q:45JS:GUWV Docker Root Dir: /home/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false
container에서 the input device is not a TTY 로그 출력시 조치
container에 저장된 데이터를 export할때 편리하게 하려고 crontab에 걸어놨는데,
다음날 보니 export된 데이터의 사이즈가 0k.
$> ls -l
total 212
-rw-r--r-- 1 root root 0 Jan 23 01:02 back-2022-01-23.sql
혹시나 싶어서 mail로그를 보니. 이런게 똭..
$> cat /var/spool/mail/root
...
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Message-Id: <20220123160541.test-machine>
Date: Mon, 24 Jan 2022 01:02:01 +0900 (KST)
the input device is not a TTY
...
생각해보니 docker exec에서 input + terminal 옵션을 넣었는데 terminal때문에 꼬인듯.
$> cat /root/db_dump.sh
#!/bin/bash
NEW_DATE=$(date +%Y-%m-%d)
OLD_DATE=$(date +%Y-%m-%d -d '-30 days')
if [[ ! -d /home/backup/$NEW_DATE ]]
then
mkdir -p /home/backup/$NEW_DATE
fi
#예전코드
$> docker exec -it postgres pg_dump -U test -d testdb > back-$NEW_DATE.sql
#변경코드
$> docker exec -i postgres pg_dump -U test -d testdb > back-$NEW_DATE.sql
음.. 잘됨.
$> ls -l
total 212
-rw-r--r-- 1 root root 102488 Jan 23 09:54 back-2022-01-23.sql
docker 와 cri-o 비교
소 개
- Container 표준규격이 없을때 Container 포맷과 런타임의 사실상 표준은 Docker가 지배.
- Google / Redhat / MS / IBM 등 Container 간의 이식성을 표준화 화기 위해 OCI(Open Container Initiative) 구성
- k8s의 컨테이너 런타임 구성을 위해 CRI(Container Runtime Interface) 등장
- RHEL 8버전이상, k8s 1.20 버전이상, Openstack 16버전이상, Openshift 4버전이상 , awx 18버전 이상에서 컨테이너 런타임을 podman으로 변경
컨테이너 런타임 레벨 종류
- low-level runtime
- 각 컨테이너별 cpu나 메모리 같은 리소스 양 제한하는 역활 (ex. runC, Container, Docker)
-
high-level runtime
- 어플리케이션을 실행하고 모니터링을 위한 API제공
- low-level 위에 실행되는 runtime (ex. containerd, docker, cri-o)
CRI-O 소개
- cri-o는 컨테이너 실행만 가능하기 때문에 이미지 생성이나 관리를 하기 위해서는 추가 Component들이 필요함. (추가 Component정보는 아래 기술)
- fork/exec 모델로 작동
- 인식가능한 파일시스템은 Overlayfs, devicemapper, btrfs 기반에서 가능하고, nfs,glusterfs,cephfs는 아직 stable하지 않음)
- docker schema v1/2 모두 지원
CRI-O 컴포넌트 종류
- podman(포드맨) : Container 실행을 위한 Tool
- Buildah(빌다) : Container 이미지 생성
- skopeo(스코피오) : 이미지 저장소 관리 Tool
crictl과 podman 차이
- crictl은 cri프로토콜을 사용해서 cli 제공
- podman은 daemon-less로 pod과 컨테이너를 관리하는 cli, docker와 동일한 cli기능 제공.
- 다만 cri-o와 직접 통신하지는 않기 때문에 cri-o에서 생성된 컨테이너를 볼수 없음.(libpod라는 podman의 컨테이너 관리 라이브러리 개발을 통해 개선할 예정)
- Docker에서 실행 혹은 빌드된 컨테이너들을 podman으로 실행 가능.
프로세스 구동모델 소개
Docker | Podman | |
---|---|---|
구동 방식 | Docker daemon 구동필요 | Daemon-less (systemd 에서 podman 실행) |
실행 권한 | 프로세스 구동시 root 권한 필요 | root-less (1024 이하 포트 실행시에만 root권한 필요) |
프로세스 실행 모델 | 서버/클라이언트 | fork/exec |
reference
- https://cri-o.io/
- https://www.openshift.com/blog/crictl-vs-podman
- https://www.s-core.co.kr/insight/view/oci%EC%99%80-cri-%EC%A4%91%EC%8B%AC%EC%9C%BC%EB%A1%9C-%EC%9E%AC%ED%8E%B8%EB%90%98%EB%8A%94-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%83%9D%ED%83%9C%EA%B3%84-%ED%9D%94%EB%93%A4%EB%A6%AC%EB%8A%94/
- https://www.redhat.com/ko/blog/introducing-cri-o-10
- https://docs.openshift.com/container-platform/3.11/crio/crio_runtime.html
Docker컨테이너 저장경로 변경방법
Docker를 rpm이나 deb같은 패키지로 설치하는 경우 기본 경로가 /var/lib/docker 인데, 대부분 /, /var가 같은 디스크를 사용하고 있기 때문에 컨테이너 용량이 커지면 OS영역에서 사용하는 디스크 사용량이 같이 증가하게 되는데…
바로 이렇게….
$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 7.7G 0 7.7G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.8G 738M 7.0G 10% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/sda2 438G 430G 8G 99% /
/dev/sdb1 2T 500G 1.5T 25% /data/
/dev/sda1 497M 275M 223M 56% /boot
overlay 438G 430G 8G 99% /var/lib/docker/overlay2/53de091a6179957607c19a836f65ce1f9f4a43308cf7b24911907958c9e9f2a2/merged
$ du -hs /var/lib/docker
420G /var/lib/docker
OS영역을 총 438G 할당했는데 Docker에서 420G를 사용하면서 전체 사용율 99%로…
/data파티션에 총 2T중 500G를 쓰고 있어서 Docker 데이터를 /data으로 이동하는것으로 조치 진행.
- Docker stop
$ systemctl stop docker
- docker 컨테이너 데이터를 /data/docker로 구성
$ cat /etc/docker/daemon.json { "data-root": "/data/docker" }
- Docker Engine버전에 따라서 daemon.json 파일로 적용되는 버전이 있고 안되는 버전이 있는 것으로 확인
- docker 데이터 이전
$ mv -f /var/lib/docker /data/docker
- docker 시작
$ systemctl start docker
- docker 설정정보 확인
$ docker info ... Docker Root Dir: /data/docker ...
k8s 강제로 pod 종료시키는 방법
k8s기반에서 강제로 pod 종료
- 죽지않는 pod 정보
[root@control1 ~]# kubectl get pod test-68d6bf4d95-zhx55 -n test_user NAME READY STATUS RESTARTS AGE test-68d6bf4d95-zhx55 1/4 Terminating 0 68d
- 강제로 pod 삭제
[root@control1 ~]# kubectl delete pod test-68d6bf4d95-zhx55 -n test_user -grace-period=0 -force warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely. pod "test-68d6bf4d95-zhx55" force deleted
- pod 정보 없는거 확인
[root@control1 ~]# kubectl get pod test-68d6bf4d95-zhx55 -n test_user Error from server (NotFound): pods "test-68d6bf4d95-zhx55" not found
kubernetes-Istio구성정보
Istio Concept & Data Flow
- Istio의 전체 Concept & Data Flow
- Concept
- ServiceMesh를 이용해 다양한 트래픽을 제어하는 역활
- http / websocket / http 등 트래픽 제어/관리에 대한 부하분산 수행
- Component별 역활
- Data Plane
- Service A / B에 구성된 Pod에는 Proxy용 Envoy Sidecar container가 배포
- Control Plane
- Mixer - 정책 설정 / ACL / 인증 역활
- Pilot : ingress routing, traffic mirroring, traffic shifting, canary deployments, circuit breaking, fault injection 역활 수행
- Galley : yaml을 istio용으로 변환 후 pilot으로 전송하고.
- Citadel : 데이터 전송시 암호화 전송(TLS) 역활, 현재 내부 통신에는 암호화과정이 없어서 사용하지 않음
- Data Plane
- 구성시 유의사항
- istio기반의 traffic shaping을 적용하려면, k8s에서 사용하는 ingres(or service nodeport)를 사용하면 적용이 안되고
service는 clusterip로 적용하고, istio ingressgateway에서 port를 정의해주어야 함.
- istio기반의 traffic shaping을 적용하려면, k8s에서 사용하는 ingres(or service nodeport)를 사용하면 적용이 안되고
Servicemesh : MSA기반의 아키텍텨는 각각 개별기능을 수행하는데, 분산 서비스 배포의 크기와 복잡성이 증가하면서 시스템을 이해하고 관리하기 더 어려워지짐. 클러스터 내부와 외부의 통신 라우팅도 복잡해지기 때문에 이러한 복잡성을 줄기기 위해 프록시를 사용하여 모든 트래픽을 확인 후 사용자가 설정한 구성에 따라 어플리케이션 트래픽을 관리하는 역활.
Istio 설치 절차
- 설치
$ curl -L https://istio.io/downloadIstio | sh - $ cd istio-1.9.2 $ ./istioctl install --set profile=default This will install the Istio 1.9.2 profile with ["Istio core"gateways"] components into the cluster. Proceed? (y/N) y ✔ Istio core installed ✔ Istiod installed ✔ Ingress gateways installed ✔ Installation complete
# Istio기반의 proxy를 설치하기 위해서 namespace에 istio용 envoy 설치
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled - istio profile별 제공 기능
- istio 서비스 상태 확인
$ kubectl get all -n istio-system NAME READY STATUS RESTARTS AGE pod/istio-ingressgateway-78d7b9b7db-zpxxf 1/1 Running 2 19d pod/istiod-85c8645bbc-4jkbj 1/1 Running 1 19d NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/istio-ingressgateway LoadBalancer 10.233.14.72 <pending> 15021:31094/TCP,80:32134/TCP,443:31338/TCP,15012:30093/TCP,15443:30233/TCP 20d service/istiod ClusterIP 10.233.43.248 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 20d service/tracing NodePort 10.233.13.45 <none> 16686:30008/TCP 17d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/istio-ingressgateway 1/1 1 1 20d deployment.apps/istiod 1/1 1 1 20d NAME DESIRED CURRENT READY AGE replicaset.apps/istio-ingressgateway-78d7b9b7db 1 1 1 20d replicaset.apps/istiod-85c8645bbc 1 1 1 20d NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/istio-ingressgateway Deployment/istio-ingressgateway <unknown>/80% 1 5 1 20d horizontalpodautoscaler.autoscaling/istiod Deployment/istiod <unknown>/80% 1 5 1 20d
- Addon 설치
- Kiali : Istio 모니터링을 위한 대쉬보드
- Jager / zipkin : 분산 시스템 모니터링
- zipkin : Twitter에서 개발한 오픈소스
- jaeger: Uber에서 개발하고 CNCF 프로젝트로 진행중인 오픈소스. (k8s환경에서는 jaeger가 효율적이라는...)
- addon 설치
$ wget http://172.21.115.91:28080/... $ kubectl apply -f ./sample/ $ kubectl get all -n istio-system NAME READY STATUS RESTARTS AGE pod/istio-ingressgateway-78d7b9b7db-zpxxf 1/1 Running 2 19d pod/istiod-85c8645bbc-4jkbj 1/1 Running 1 19d pod/jaeger-7f78b6fb65-jcrgz 1/1 Running 1 17d pod/kiali-dc84967d9-cqn8v 1/1 Running 1 19d pod/prometheus-7bfddb8dbf-vsddf 2/2 Running 4 19d NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/istio-ingressgateway LoadBalancer 10.233.14.72 <pending> 15021:31094/TCP,80:32134/TCP,443:31338/TCP,15012:30093/TCP,15443:30233/TCP 20d service/istiod ClusterIP 10.233.43.248 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 20d service/jaeger-collector ClusterIP 10.233.35.73 <none> 14268/TCP,14250/TCP 17d service/kiali NodePort 10.233.21.50 <none> 20001:30007/TCP,9090:31990/TCP 20d service/prometheus ClusterIP 10.233.24.217 <none> 9090/TCP 20d service/tracing NodePort 10.233.13.45 <none> 16686:30008/TCP 17d service/zipkin ClusterIP 10.233.34.17 <none> 9411/TCP 17d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/istio-ingressgateway 1/1 1 1 20d deployment.apps/istiod 1/1 1 1 20d deployment.apps/jaeger 1/1 1 1 17d deployment.apps/kiali 1/1 1 1 20d deployment.apps/prometheus 1/1 1 1 20d NAME DESIRED CURRENT READY AGE replicaset.apps/istio-ingressgateway-78d7b9b7db 1 1 1 20d replicaset.apps/istiod-85c8645bbc 1 1 1 20d replicaset.apps/jaeger-7f78b6fb65 1 1 1 17d replicaset.apps/kiali-dc84967d9 1 1 1 20d replicaset.apps/prometheus-7bfddb8dbf 1 1 1 20d NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/istio-ingressgateway Deployment/istio-ingressgateway <unknown>/80% 1 5 1 20d horizontalpodautoscaler.autoscaling/istiod Deployment/istiod <unknown>/80% 1 5 1 20d
- 대쉬보드 외부 접속하기
- kiali : http://{{서버IP}}:30007
- jaeger: http://{{서버IP}}:30008
1.삭제$ istioctl x uninstall --purge kubectl delete namespace istio-system
- 시스템 설정을 위한 설정값 안내
Component list
항목 용도 기타 gateway http / tcp를 연결하기 위해 구성하는 로드밸런서 virtualservice service 게이트웨이에 바인딩 후 트래픽을 구성된 여러 엔드포인트로 전달 (트래픽 비율설정) virtualservice version(a.k.a subset) 특정 서비스에 대해 어플리케이션 바이너리의 버전 변경을 실행하는 집합 virtualservice source 서비스를 호출하는 다운스트림용 클라이언트 virtualservice host 클라이언트가 서비스 연결할때 사용하는 주소 destinationRule 라우팅 규칙을 처리한 후 연결할 네트워크 서비스를 설정 tcproute tcp트래픽에 대해 라우팅 규칙을 위한 조건 설정 tcproute match 활성화할 규칙조건 tcproute route 연결할 대상 - Example yml
- gateway 설정 (tcp/30011에 대해 gateway 설정)
$vi gateway.yml --- apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: gateway namespace: test spec: selector: app: test servers: - hosts: - '*' port: name: tcp number: 30011 protocol: TCP
- gateway 설정 (tcp/30011에 대해 gateway 설정)
- VirtualService 설정 (tcp/30011이 들어오면 service111-1, service111-2의 tcp/8080으로 연결하되 50%씩 트래픽 분할 처리)
$ vi vs.yaml --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: test-vs namespace: test spec: gateways: - gateway hosts: - appid111 tcp: - match: - port: 30011 route: - destination: host: appid111-1 port: number: 3390 subset: v1 weight: 50 - destination: host: appid111-2 port: number: 3390 subset: v2 weight: 50
- destinationrule 설정 (service111에 대해 v1, v2 설정)
$ vi rule.yml --- apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: test-rule namespace: test spec: host: appid111 subsets: - labels: version: 'v1' name: v1 - labels: version: 'v2' name: v2 trafficPolicy: loadBalancer: simple: ROUND_ROBIN tls: mode: DISABLE
reference
https://istio.io/latest/docs/setup/getting-started/
podman기반의 컨테이너 정보 설정
insecure registry 설정
- podman기반에서 insecure registry 설정방법
$> vi /etc/containers/registries.conf ... unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "registry.centos.org", "docker.io", "20.20.20.20", "10.10.10.10"] ... [[registry]] location = "10.10.10.10:80" insecure = true [[registry]] location = "20.20.20.20:80" insecure = true
- daemonless이기 때문에 바로 적용
$> podman login 10.10.10.10:80 Username: Password: Login Successed
- 기존 Docker에서 컨테이너 내려받을때는 포트정보가 없어도 되었지만, podman에서 내려받을때는 :80을 꼭 명시해야 함(default가 443이기 때문에 포트정보가 없는 경우 443으로 내려받으려고 시도함
컨테이너 저장경로 변경
- podman 기반에서 컨테이너 스토리지 경로 변경
$> vi /etc/containers/storage.conf ... runroot = "/service/containers/storage" graphroot = "/service/containers/storage" ...
Podman기반의 DNS연동
podman을 사용할 경우 네트워크는 cni를 사용하게 되는데, 기본값은 호스트의 DNS를 사용하기 때문에 컨테이너 내부의 DNS를 사용해야할 경우 호출이 불가능.
- docker기반에서 컨테이너간 dns통신상태 확인
$> docker exec -it awx_task ping redis PING redis (172.18.0.5) 56(84) bytes of data. 64 bytes from awx_redis.awxcompose_default (172.18.0.5): icmp_seq=1 ttl=64 time=0.240 ms 64 bytes from awx_redis.awxcompose_default (172.18.0.5): icmp_seq=2 ttl=64 time=0.090 ms 64 bytes from awx_redis.awxcompose_default (172.18.0.5): icmp_seq=3 ttl=64 time=0.074 ms ^C --- redis ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 3ms rtt min/avg/max/mdev = 0.074/0.134/0.240/0.075 ms
- podman 기반에서 컨테이너간 dns통신상태 확인
$ podman exec -it awx_task ping redis ping: redis: Name or service not known
조치사항
- cni에 dnsname 플러그인 설치 및 NetworkManager 연동
- dns패키지 설치
$> yum install dnsmasq podman-plugins -y
- NetworkManager dnsname 플러그인 연동 후 서비스 재시작
$> vi /etc/NetworkManager/NetworkManager.conf ... [main] dns=dnsmasq ...
-
NetworkManager에 dnsname 플러그인 설치 여부 확인
$> ls -l /usr/libexec/cni/ 합계 73252 ... -rwxr-xr-x 1 root root 3980624 2월 2 09:00 dnsname ...
- cni에 dnsname 플러그인 설치
$> vi /etc/cni/net.d/awxcompose_default.conflist ... { "type": "firewall", "backend": "" }, { "type": "tuning" }, { "type": "dnsname", "domainName": "awxcompose_default", "capabilities": { "aliases": true } } ] }
- 서버 재부팅
- 내부 통신 확인
$> podman exec -it awx_task ping redis PING redis (10.89.0.2) 56(84) bytes of data. 64 bytes from awx_redis (10.89.0.2): icmp_seq=1 ttl=64 time=0.119 ms 64 bytes from awx_redis (10.89.0.2): icmp_seq=2 ttl=64 time=0.047 ms 64 bytes from awx_redis (10.89.0.2): icmp_seq=3 ttl=64 time=0.070 ms 64 bytes from awx_redis (10.89.0.2): icmp_seq=4 ttl=64 time=0.072 ms ^C --- redis ping statistics --- 7 packets transmitted, 7 received, 0% packet loss, time 155ms rtt min/avg/max/mdev = 0.047/0.069/0.119/0.021 ms
podman사용하기
-
docker없이 컨테이너 실행하기
- podman-docker 패키지를 통해 docker가 설치되어 있지 않아도 docker 명령어를 실행할 수 있습니다.
-
사실 커맨드가 매핑도이 있는것이고 실제로는 podman을 실행하게 됩니다.
$> yum install podman-docker -y 마지막 메타자료 만료확인 1:40:24 이전인: 2022년 02월 07일 (월) 오후 12시 21분 09초. 종속성이 해결되었습니다. ================================================================================= 꾸러미 구조 버전 레포지터리 크기 ================================================================================= 설치 중: podman-docker noarch 3.3.1-9.0.1.module+el8.5.0+20416+d687fed7 ol8_appstream 56 k 연결 요약 ================================================================================= 설치 1 꾸러미 총계 내려받기 크기: 56 k 설치된 크기 : 230 꾸러미 내려받기중: podman-docker-3.3.1-9.0.1.module+el8.5.0+20416+d 288 kB/s | 56 kB 00:00 --------------------------------------------------------------------------------- 합계 284 kB/s | 56 kB 00:00 연결 확인 실행 중 연결 확인에 성공했습니다. 연결 시험 실행 중 연결 시험에 성공했습니다. 연결 실행 중 준비 중 : 1/1 설치 중 : podman-docker-3.3.1-9.0.1.module+el8.5.0+20416+d687f 1/1 스크립트릿 실행 중: podman-docker-3.3.1-9.0.1.module+el8.5.0+20416+d687f 1/1 [/usr/lib/tmpfiles.d/pesign.conf:1] Line references path below legacy directory /var/run/, updating /var/run/pesign → /run/pesign; please update the tmpfiles.d/ drop-in file accordingly. 확인 중 : podman-docker-3.3.1-9.0.1.module+el8.5.0+20416+d687f 1/1 설치되었습니다: podman-docker-3.3.1-9.0.1.module+el8.5.0+20416+d687fed7.noarch 완료되었습니다!
# yum module install container-tools -y 마지막 메타자료 만료확인 0:09:24 이전인: 2022년 02월 07일 (월) 오후 03시 57분 13초. 종속성이 해결되었습니다. ================================================================================= 꾸러미 구조 버전 레포지터리 크기 ================================================================================= 그룹/모듈 꾸러미 설치: crun x86_64 1.0-1.module+el8.5.0+20416+d687fed7 ol8_appstream 193 k python3-podman noarch 3.2.0-2.module+el8.5.0+20416+d687fed7 ol8_appstream 148 k udica noarch 0.2.5-2.module+el8.5.0+20416+d687fed7 ol8_appstream 51 k 종속 꾸러미 설치 중: python3-pytoml noarch 0.1.14-5.git7dea353.el8 ol8_appstream 25 k python3-pyxdg noarch 0.25-16.el8 ol8_appstream 94 k 모듈 프로파일 설치: container-tools/common 연결 요약 ================================================================================= 설치 5 꾸러미 총계 내려받기 크기: 510 k 설치된 크기 : 1.6 M 꾸러미 내려받기중: (1/5): crun-1.0-1.module+el8.5.0+20416+d687fed7. 1.6 MB/s | 193 kB 00:00 (2/5): python3-podman-3.2.0-2.module+el8.5.0+204 65 kB/s | 148 kB 00:02 (3/5): python3-pytoml-0.1.14-5.git7dea353.el8.no 10 kB/s | 25 kB 00:02 (4/5): python3-pyxdg-0.25-16.el8.noarch.rpm 39 kB/s | 94 kB 00:02 (5/5): udica-0.2.5-2.module+el8.5.0+20416+d687fe 33 kB/s | 51 kB 00:01 --------------------------------------------------------------------------------- 합계 133 kB/s | 510 kB 00:03 연결 확인 실행 중 연결 확인에 성공했습니다. 연결 시험 실행 중 연결 시험에 성공했습니다. 연결 실행 중 준비 중 : 1/1 설치 중 : python3-pyxdg-0.25-16.el8.noarch 1/5 설치 중 : python3-pytoml-0.1.14-5.git7dea353.el8.noarch 2/5 설치 중 : python3-podman-3.2.0-2.module+el8.5.0+20416+d687fed7 3/5 설치 중 : udica-0.2.5-2.module+el8.5.0+20416+d687fed7.noarch 4/5 설치 중 : crun-1.0-1.module+el8.5.0+20416+d687fed7.x86_64 5/5 스크립트릿 실행 중: crun-1.0-1.module+el8.5.0+20416+d687fed7.x86_64 5/5 확인 중 : crun-1.0-1.module+el8.5.0+20416+d687fed7.x86_64 1/5 확인 중 : python3-podman-3.2.0-2.module+el8.5.0+20416+d687fed7 2/5 확인 중 : python3-pytoml-0.1.14-5.git7dea353.el8.noarch 3/5 확인 중 : python3-pyxdg-0.25-16.el8.noarch 4/5 확인 중 : udica-0.2.5-2.module+el8.5.0+20416+d687fed7.noarch 5/5 설치되었습니다: crun-1.0-1.module+el8.5.0+20416+d687fed7.x86_64 python3-podman-3.2.0-2.module+el8.5.0+20416+d687fed7.noarch python3-pytoml-0.1.14-5.git7dea353.el8.noarch python3-pyxdg-0.25-16.el8.noarch udica-0.2.5-2.module+el8.5.0+20416+d687fed7.noarch
완료되었습니다! - docker의 socket api가 지원되기 때문에 podman-docker 패키지를 설치하면 /var/run/docker.sock과 /var/run/podman/podman.sock의 링크를 설정하기 때문에 docker-py, docker-compose를 이용한 docker api도 그대로 사용할 수 있습니다.
- podman에서 지원하지 않는 docker 옵션은 네트워크, 노드, 플러그인, 이름변경, 시크릿, 서비스, 스택, docker swarm이 대상입니다.
-
Rooless설정
- 호스트 컨테이너 스토리지 경로는 사용자 정보에 따라 달라집니다. (root - /var/lib/containers/storage, non root - $HOME/.local/share/containers/storage)
- rootless 컨테이너는 1024미만의 포트에 액세스 할 수 없습니다. (tcp/80을 사용하는 apache의 경우 서비스에서는 tcp/80을 표시하시만 서버 외부에서 실제 접속은 불가능)
- 1024 이하 포트를 사용하려면 커널값 변경을 통해 임시로 사용할 수는 있으나, 프로덕션 환경에서는 사용하는것은 권장되지 않습니다. (테스트 목적)
$> echo 80 > /proc/sys/net/ipv4/ip_unprivileged_port_start
- 8.1부터 rootless Containers기능을 사용하면 일반사용자로 컨테이너 실행할 수 있습니다. (rootless는 기본기능)
$> podman pull docker.io/library/httpd Trying to pull docker.io/library/httpd:latest... Getting image source signatures Copying blob 5eb5b503b376 done Copying blob 10c4d45228bf done Copying blob a43a76ccc967 done Copying blob 942bd346e7f7 done Copying blob cdb155854ae6 done Copying config a8ea074f45 done Writing manifest to image destination Storing signatures a8ea074f4566addcd01f9745397f32be471df4a4abf200f0f10c885ed14b1d28 [user@test~]$ docker image ls Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/httpd latest a8ea074f4566 11 days ago 148 MB
-
레지스트리 구성
- registries.conf에 컨테이너를 내려받기 위한 레지스트리 목록이 저장되어 있습니다, 해당 파일에서 검색할 레지스트리를 설정 할 수 있습니다.
$> vi /etc/containers/registries.conf ... unqualified-search-registries = ["container-registry.oracle.com", "docker.io", "container.test.com"] ...
- test.com은 TLS 없이 pull 설정
$> vi /etc/containers/registries.conf ... [[registry]] location="container.test.com" insecure = true ...
- 특정 레지스트리 검색 차단
$> vi /etc/containers/registries.conf ... [[registry]] location="container.test.com" blocked = true ...
- registries.conf에 컨테이너를 내려받기 위한 레지스트리 목록이 저장되어 있습니다, 해당 파일에서 검색할 레지스트리를 설정 할 수 있습니다.
- 이미지 검사
- skopeo 명령어를 통해 이미지 정보를 확인할 수 있습니다.
- httpd container 정보 확인 방법
# skopeo inspect docker://docker.io/library/httpd:latest { "Name": "docker.io/library/httpd", "Digest": "sha256:5cc947a200524a822883dc6ce6456d852d7c5629ab177dfbf7e38c1b4a647705", "RepoTags": [ "2", "2-alpine", "2-alpine3.13", "2-alpine3.14", "2-alpine3.15", "2-bullseye", "2-buster", "2.2", "2.2-alpine", "2.2.29", "2.2.31", "2.2.31-alpine", "2.2.32", "2.2.32-alpine", "2.2.34", "2.2.34-alpine", "2.4", "2.4-alpine", "2.4-alpine3.13", "2.4-alpine3.14", "2.4-alpine3.15", "2.4-bullseye", "2.4-buster", "2.4.10", "2.4.12", "2.4.16", "2.4.17", "2.4.18", "2.4.20", "2.4.23", "2.4.23-alpine", "2.4.25", "2.4.25-alpine", "2.4.27", "2.4.27-alpine", "2.4.28", "2.4.28-alpine", "2.4.29", "2.4.29-alpine", "2.4.32", "2.4.32-alpine", "2.4.33", "2.4.33-alpine", "2.4.34", "2.4.34-alpine", "2.4.35", "2.4.35-alpine", "2.4.37", "2.4.37-alpine", "2.4.38", "2.4.38-alpine", "2.4.39", "2.4.39-alpine", "2.4.41", "2.4.41-alpine", "2.4.43", "2.4.43-alpine", "2.4.46", "2.4.46-alpine", "2.4.47", "2.4.47-alpine", "2.4.48", "2.4.48-alpine", "2.4.48-alpine3.13", "2.4.48-alpine3.14", "2.4.48-buster", "2.4.49", "2.4.49-alpine", "2.4.49-alpine3.14", "2.4.49-buster", "2.4.50", "2.4.50-alpine", "2.4.50-alpine3.14", "2.4.50-buster", "2.4.51", "2.4.51-alpine", "2.4.51-alpine3.14", "2.4.51-alpine3.15", "2.4.51-bullseye", "2.4.51-buster", "2.4.52", "2.4.52-alpine", "2.4.52-alpine3.15", "2.4.52-bullseye", "alpine", "alpine3.13", "alpine3.14", "alpine3.15", "bullseye", "buster", "latest" ], "Created": "2022-01-26T08:38:51.175633696Z", "DockerVersion": "20.10.7", "Labels": null, "Architecture": "amd64", "Os": "linux", "Layers": [ "sha256:5eb5b503b37671af16371272f9c5313a3e82f1d0756e14506704489ad9900803", "sha256:a43a76ccc96739928c7e884f2210dde01ae5b1fd8822f8cdd56e6ba64ec3125a", "sha256:942bd346e7f719d26e022dfc42eea7e1fa5cf9ad60ec80ed0ef79ded05288be6", "sha256:cdb155854ae6a9e25834459a7c9dfc7be157a2ebfca5adbdb036aeea43ce3128", "sha256:10c4d45228bf56285a1e2c828d60e34d8413ee80e1abd738ef190be843d9dc1e" ], "Env": [ "PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HTTPD_PREFIX=/usr/local/apache2", "HTTPD_VERSION=2.4.52", "HTTPD_SHA256=0127f7dc497e9983e9c51474bed75e45607f2f870a7675a86dc90af6d572f5c9", "HTTPD_PATCHES=" ]
podman에서 컨테이너가 실행되지 않을때 조치방법
podman에서 컨테이너 띄울때 아래 메시지가 나오면서 정상적으로 실행되지 않는 경우가 있어요.
실행절차
$> podman run -d --name=test
...
Error: runc: container_linux_go:370: staring container process caised: error adding seccomp filter rule for syscall bdflush: permission denied
컨테이너 상태를 보면 아래와 같이 state가 구동(Up)이 아니라 생성(created)만 되게 되어요
$> docker ps -a
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd3896eb439d localhost:5000 5 months ago Created 0.0.0.0:80->80/tcp test
발생원인
1. podman/runc의 버그로 보임
조치방안 (한꺼번에 다 할 필요는 없고 1번해보고 해결이 안되면 2번, 2번도 안되면 3번순으로 진행)
- podman 패키지 업데이트
$> yum update podman -y ...
- podman 실행 옵션에서 security설정 변경
$> podman run -d --security-opt=seccomp=unconfined --name=test ...
- runtime 종류 변경
$> podman run --runtime crun -d --name=test ...
확인방법
$> docker ps -a
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd3896eb439d localhost:5000 5 months ago Up 2 weeks ago 0.0.0.0:80->80/tcp test
etcd의 member확인
k8s의 DB성격인 etcd의 상태 점검시 확인할 수 있는 몇가지 포인트들
- member list
$> /usr/local/bin/etcdctl.sh -w table member list +------+---------+---------+-----------+------------+ | ID | TATUS | PEER ADDRS | CLIENT ADDRESS | IS LEARNER | +------+---------+---------+-----------+------------+ | abcd | 3.4.13 | 11 MB | true | false | | 1234 | 3.4.13 | 11 MB | false | false | | efgh | 3.4.13 | 11 MB | false | false | +------+---------+---------+-----------+------------+
- endpoint (데이터 상태 크기 확인)
$> /usr/local/bin/etcdctl.sh -w table endpoint status --cluster=true +---------------------------+------+---------+---------+-----------+------------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | +---------------------------+------+---------+---------+-----------+------------+ | https://192.168.0.10:2379 | abcd | 3.4.13 | 11 MB | true | false | | https://192.168.0.11:2379 | 1234 | 3.4.13 | 11 MB | false | false | | https://192.168.0.12:2379 | efgh | 3.4.13 | 11 MB | false | false | +---------------------------+------+---------+---------+-----------+------------+
kubeadm 노드추가
클러스터 노드 추가시 진행되는 작업절차
- 클러스터 마스터 노드에서 token 발급진행
$> kubeadm token create --print-join-command 123123123
- join할 노드에서 아래 명령어 수행 : 추가하 노드는 kubeadm / kubelet 등 기본적인 provisioning이 되어 있어야 함.
$> kubeadm join {{ masterip }}:6443 --node-name {{ 호스트네임 }} --token 123123 --discovery-token-ca-cert-hash abcd123
etcd member 제외 방법
kuebernetes DB격인 etcd의 member리스트를 제외한느 절차를 기술한다.
다중 마스터(3대로 구현)되어 있을때 특정 노드를 제외하는 방법이다.
- etcd memver list 확인
$> cd /usr/local/bin $> ./etcdctl.sh -w table endpoint status --cluter=true +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------| | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------| | https://1.2.3.4:2379 | abcd | 3.4.13 | 11 MB | true | false | 16 | 2607488 | 2607488 | | | https://5.6.7.8:2379 | efgh | 3.4.13 | 11 MB | false | false | 16 | 2607488 | 2607488 | | | https://9.8.7.6:2379 | ijkl | 3.4.13 | 11 MB | false | false | 16 | 2607488 | 2607488 | | +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------|
- 제외할 인스턴스 ID입력
$> ./etcdctl.sh member remove efgh Memeber efgh removed from cluster 1234
- 제외상태 확인
$> cd /usr/local/bin $> ./etcdctl.sh -w table endpoint status --cluter=true +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------| | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------| | https://1.2.3.4:2379 | abcd | 3.4.13 | 11 MB | true | false | 16 | 2607488 | 2607488 | | | https://9.8.7.6:2379 | ijkl | 3.4.13 | 11 MB | false | false | 16 | 2607488 | 2607488 | | +----------------------+------+---------+----------+-----------+------------+------------+------------+--------------------+--------|
컨테이너 구동시 unknown server host 메시지 뜨면서 구동실패
발생현상
컨테이너 내부에서 통신시 호스트를 못찾는 문제가 있어서(WEB ->DB) 구동실패
원 인
Docker 내부에서 hosts를 찾지 않고 docker-dns.conf를 따라서 외부 DNS를 참조해서 리졸빙하는것으로 보임.
조치방법
docker-dns를 제외하고 구동.
$> mv /etc/systemd/system/docker.service.d/docker-dns.conf /etc/systemd/system/docker.service.d/docker-dns.conf_ori
$> systemctl daemon-reload
$> systemctl restart docker
pod 구동될때 Imageinspecterror or readlink invalid argument error 메시지 발생
발생현상
- pod 구동될때 Imageinspecterror 메시지를 출력하면서 구동되지 않는 문제
$> kubectl describe pod {{ pod명 }} ... Events ... Imageinspecterror
- docker data root가 변경된 경우 일부 pod가 캐싱된 경로를 가지고 있어서 발생하는 것으로 보임 - Docker컨테이너 저장경로 변경방법
조치방법
- docker 캐쉬정보 삭제
$> docker system prune -af $> docker volume prune -af
- pod 삭제 (auto healing 기능에 따라 자동으로 다시 배포됨)
$> kubectl delete pod --grace-period=0 --force {{ pod명 }}
워커노드 제외방법
사전 설명
k8s환경에서 특정 노드 제외할때 그냥 삭제해도 kube scheduling에 의해 재배치가 있긴하지만 계획된 정지 작업같은 작업이 있는경우
보다 안정적으로 노드를 제외하려면 cordon / drain 절차를 거치면 좋습니다.
cordon / drain은 약간의 차이가 있는데, cordon의 경우 단순 스케쥴링을 제외하는 절차, drain의 경우 제외할 노드를 모두 제거하는 절차를 수행합니다. (drain은 cordon절차를 포함합니다.)
작업절차
-
cordon 설정
- 노드 정보 확인
$> kubectl get no NAME STATUS ROLES AGE VERSION masr1 Ready control-plane,master 37d v1.23.7 work1 Ready <none> 37d v1.23.7 work2 Ready <none> 37d v1.23.7
- cordon 수행 (work1노드를 제외할껍니다.)
$> kubectl cordon work1 node/work1 cordoned $> kubectl get no NAME STATUS ROLES AGE VERSION masr1 Ready control-plane,master 37d v1.23.7 work1 Ready <none> 37d v1.23.7 work2 Ready,SchedulingDisabled <none> 37d v1.23.7
- 노드 정보 확인
-
drain 수행
- 해당 노드에 daemonset으로 구동되는 pod가 있거나 local storage가 구동되고 있는 경우 drain 작업이 수행되지 않습니다.
kubectl drain work2 node/work2 already cordoned error: unable to drain node "work2", aborting command... There are pending nodes to be drained: k8sw2 cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/calico-node-fb862, kube-system/kube-proxy-4qhsx, kube-system/nodelocaldns-6cptm cannot delete Pods with local storage (use --delete-emptydir-data to override): kubernetes-dashboard/dashboard-metrics-scraper-66dd8bdd86-6cnbv, kubernetes-dashboard/kubernetes-dashboard-844749bcff-mmpq2
- 강제로 drain 처리
kubectl drain work2 --ignore-daemonsets --delete-emptydir-data node/work2 already cordoned WARNING: ignoring DaemonSet-managed Pods: kube-system/calico-node-fb862, kube-system/kube-proxy-4qhsx, kube-system/nodelocaldns-6cptm evicting pod kubernetes-dashboard/kubernetes-dashboard-844749bcff-mmpq2 evicting pod cert-manager/cert-manager-cainjector-75c94654d-r7trs evicting pod cert-manager/cert-manager-webhook-d4fd4f479-cr6z2 evicting pod gitlab-agent/house-gitlab-agent-v1-586d6d6797-vm68t evicting pod kube-system/coredns-657959df74-j2zbq evicting pod kubernetes-dashboard/dashboard-metrics-scraper-66dd8bdd86-6cnbv pod/cert-manager-cainjector-75c94654d-r7trs evicted pod/cert-manager-webhook-d4fd4f479-cr6z2 evicted pod/house-gitlab-agent-v1-586d6d6797-vm68t evicted pod/kubernetes-dashboard-844749bcff-mmpq2 evicted pod/dashboard-metrics-scraper-66dd8bdd86-6cnbv evicted pod/coredns-657959df74-j2zbq evicted node/work2 evicted
- 해당 노드에 daemonset으로 구동되는 pod가 있거나 local storage가 구동되고 있는 경우 drain 작업이 수행되지 않습니다.
-
작업완료
- 작업이 끝난노드를 다시 클러스터로 포함시키면 됩니다.
kubectl uncordon work2 node/work2 already uncordoned
- 스케쥴링 활성화 확인
$> kubectl get no NAME STATUS ROLES AGE VERSION masr1 Ready control-plane,master 37d v1.23.7 work1 Ready <none> 37d v1.23.7 work2 Ready <none> 37d v1.23.7
- 작업이 끝난노드를 다시 클러스터로 포함시키면 됩니다.
특정 노드에만 배포할 수 있는 taint 설정하기
k8s를 사용하다보면 특정 서버또는 특정환경에 매칭되는 pod만 배포할 경우가 필요합니다.
예를들면.... 디스크 타입이 ssd 장착된 노드와 hdd가 장착된 노드로 분리되어 있는 경우 disk io의 성능을 끌어올리려면 hdd보다는 ssd가 낫겠죠.
그렇게 특정 노드에 속성을 걸고 pod에 배포하기 위해서는 taint + Tolerations 이라는 기능을 사용하면 됩니다.
taint는 노드의 속성값으로 추가하는 것이고, toleration은 적용된 taint에 어떻게 반영할것인지를 정의하는 겁니다.
taint = node2의 type은 ssd이야
toleration = type 이 ssd로 정의된 노드에 배포해줘.
- 스케쥴 정보
스케쥴 정보 용 도 NoSchedule
앞으로 배포될 리소스에 대해서 적용 (현재 배포된 POD는 현상유지) PreferNoSchedule 앞으로 배포될 리소스에 대해서 적용하지만 어쩔수 없을때는 무시하고 배포
(현재 배포된 POD는 현상유지)NoExecute 현재 배포된 리소스와 앞으로 배포될 리소스 모두 정책에 맞지 않으면 모두 제거 - 노드에 taint 적용하기
- taint 정보 확인
$> kubectl get nodes -o custom-columns=node:.metadata.name,taint:.spec.taints node taint controlplane [map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]] node01 <none>
taint 설정 없는거 확인하였쥬?
- taint 설정해봅시다.
$> kubectl taint node node01 disk=ssd:NoSchedule node/node01 tainted
- 이제 taint 설정 한거 확인해봅시다.
$> kubectl get nodes -o custom-columns=node:.metadata.name,taint:.spec.taints node taint controlplane [map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]] node01 [map[effect:NoSchedule key:disk value:ssd]]
- taint 정보 확인
- deployment에 toleration 정의하기
- deployment에 toleration 정의하기
$> vi deploy.yaml ... spec: containers: - image: nginx ... tolerations: - key: "disk" operator: "Equal" value: "ssd" effect: "NoSchedule" ...
- 배포하기
$> kubectl apply -f deploy.yaml
- deployment에 toleration 정의하기
- 노드에 적용했던 taint 정보 삭제 (적용했던 정책에서 -를 추가하면 삭제된다)
$> kubectl taint node node01 disk=ssd:NoSchedule- node/node01 untainted
- 지연된 pod 제거 방법
- toleration에서 tolerationSeconds 값(초기준)을 추가하면 정의된 초 이후로 pod가 제거된다.
$> vi deploy.yaml ... tolerations: - key: "disk" operator: "Equal" value: "ssd" effect: "NoExecute" tolerationSeconds: 3600 ...
- toleration에서 tolerationSeconds 값(초기준)을 추가하면 정의된 초 이후로 pod가 제거된다.