velero 가 설치되지 않은 클러스터에서 배포된 자원 manifest 정보를 txt 파일에 저장하는 bash shell script 코드. 

kubectl ... -o yaml 과 함께 아래 neat 를 설치 및 조합하면 기타 타임스탬프 등 불필요한 정보를 제외한 readable 버전으로 저장이 가능합니다.

해당 조합으로 저장 시 txt 대신 yaml 로 저장하고 배포가능한 형식으로 테스트할 수 있습니다.

kubectl krew install neat # neat 설치 명령어.

 

 

그 전에 krew 가 설치되어있지 않다면 다음을 이용해 미리 설치해 둡니다.

 

# run a script by copy and paste to your command line
(
  set -x; cd "$(mktemp -d)" &&
  OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
  ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e
 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
  curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.tar.gz" &&
  tar zxvf krew.tar.gz &&
  KREW=./krew-"${OS}_${ARCH}" &&
  "$KREW" install krew
)

# set the path env of krew
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

 

< Code Sample >

#!/bin/bash

# 백업할 네임스페이스 지정
NAMESPACES=("apples" "bananas" "grapes" "strawberries" "melons")

# 각 네임스페이스의 리소스 정보를 txt 파일로 저장
for namespace in "${NAMESPACES[@]}"
do
    echo "네임스페이스 $namespace 리소스 정보 저장 중..."
    
    # 네임스페이스의 모든 리소스 정보 가져오기
    kubectl get all -n "$namespace" -o yaml > "$namespace-resources.txt"
done

# gp2, gp3, default-efs StorageClass 정보 저장
echo "StorageClass 정보 저장 중..."
kubectl get storageclass gp2 -o yaml > gp2-storageclass.txt
kubectl get storageclass gp3 -o yaml > gp3-storageclass.txt
kubectl get storageclass default-efs -o yaml > default-efs-storageclass.txt

echo "모든 정보가 txt 파일로 저장되었습니다."

 

python3이상, boto3 설치 필요

import boto3
import time

aws_profile = "your aws profile"
aws_region = "your region"

session = boto3.Session(
    profile_name=aws_profile,
    region_name=aws_region
)

eks_client = session.client('eks')

cluster_name = 'your cluster name'

# 해당 클러스터의 모든 Fargate 프로필 이름 가져오기
response = eks_client.list_fargate_profiles(clusterName=cluster_name)
profiles = response['fargateProfileNames']

# 각 Fargate 프로필 삭제
for profile in profiles:
    print(f"Deleting Fargate profile: {profile}")
    eks_client.delete_fargate_profile(clusterName=cluster_name, fargateProfileName=profile)
    
    # 삭제 상태 확인
    while True:
        try:
            eks_client.describe_fargate_profile(clusterName=cluster_name, fargateProfileName=profile)
            print(f"Waiting for {profile} to be deleted...")
            time.sleep(10)  
        except eks_client.exceptions.ResourceNotFoundException:
            print(f"{profile} deleted.")
            break

print("All Fargate profiles have been deleted.")

 

※ 쿠버네티스 컨피그('~/.kube/config') 에 여러 계정의 여러 클러스터가 저장되어있고 컨텍스트(context) 전환할 때

어떤 클러스터 컨텍스트를 사용하고 있는지 표시하고 싶은 경우 사용

 

  • Bash 쉘에서의 설정

'~/.bashrc' 또는 '~/.bash_profile' 파일에 아래 줄 추가

export PS1='\[\e]0;\u@\h: \w\a\]\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] \[\033[01;36m\]($(kubectl config current-context))\[\033[00m\] $ '

 

설정 파일 적용

source ~/.bashrc

 

Context Name은 AWS 서비스의 경우 꼭 Arn을 다 입력하지 않고 클러스터 명 정도만 간편하게 적어 사용할 수 있다.

ETCDCTL version 2

 

etcdctl backup
etcdctl cluster-health
etcdctl mk
etcdctl mkdir
etcdctl set

 

ETCDCTL version 3

 

etcdctl snapshot save 
etcdctl endpoint health
etcdctl get
etcdctl put

 

Setting API version 

export ETCDCTL_API=<number>

Setting path to certificate files for ETCDCTL to authenticate ETCD API server

--cacert /etc/kubernetes/pki/etcd/ca.crt     
--cert /etc/kubernetes/pki/etcd/server.crt     
--key /etc/kubernetes/pki/etcd/server.key

An example command with kubectl pa

kubectl exec etcd-master01 -n kube-system -- sh -c "ETCDCTL_API=3 etcdctl get / --prefix --keys-only --limit=10 --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/server.crt  --key /etc/kubernetes/pki/etcd/server.key"

 

-. 쿠버네티스에서 기본적으로 파드들을 배포, 업데이트 등 관리하기 위해 사용하는 yaml 템플릿 종류에 대한 정리입니다.

 

1. DaemonSet

  • Purpose: 각 노드에 특정 파드를 실행하고 싶을 때 이용. A DaemonSet ensures a specific pod runs on each nodes in the Kubernetes cluster. 주로 모니터링 에이전트, 로그 수집, 백그라운드로 돌아가는 작업들 등 각 노드에 특정 파드의 복제본 파드를 실행시키거나 하는 상황에서 사용. it's commonly used for log collection, monitoring agents, and background tasks, so on.
  • Advantage: 데몬셋은 각 노드 별로 해당 파드를 동일하게 복제하여 일치성을 유지하는데 도움이 되는 방식. 해당 방법으로 동일 클러스터 내의 모든 호스트로부터 데이터를 수집하고 워크로드를 분산하는데 도움이 된다. DaemonSets help maintain consistency across nodes by running a pod on each node. easy to distribute workloads and collect data from every host in the cluster.

데몬셋으로 서비스 생성하는 예: yaml 방식 배포

하기 방식으로 서비스에 맞게 yaml 파일을 생성하고, kind는 DaemonSet으로 생성하여 create 또는 apply로 명령하여 데몬셋을 실행한다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: servicename-daemonset
spec:
  selector:
    matchLabels:
      app: servicename
  template:
    metadata:
      labels:
        app: appname
    spec:
      containers:
      - name: example
        image: example:latest

 

2. StatefulSet

  • Purpose: Stateful 한 어플리케이션 배포에 사용한다. 즉 배포대상 파드가 유일무이한 특성을 가지거나 네트워크 안정성이 필요한 서비스일때 사용한다. Although ReplicaSets are not typically used directly, this can manage stateful applications where each pod has a unique identity and stable network identity, for databases like MySQL, messaging systems like Kafka or  any application which needs stable and persistent network identities.
  • Advantage: StatefulSet 은 파드가 생성될때 순서대로 고유의 서비스를 유지하면서 스케일링 되도록 한다. StatefulSets ensure pods are created and scaled in order, preserving their identities, which required data needs to be retained and moved with the pods. 데이터 손실없이 pod 변경이 필요한 stateful 어플리케이션에 적합하다.

StatefulSet으로 서비스 생성하는 예: yaml 방식 배포

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: yourservice-name
spec:
  selector:
    matchLabels:
      app: service-name
  serviceName: "example"
  replicas: 3
  template:
    metadata:
      labels:
        app: service-name
    spec:
      containers:
      - name: service-name
        image: service-name:latest
        ports:
        - containerPort: 00
        volumeMounts:
        - name: service-name-persistent-storage
          mountPath: /var/lib/service-name
  volumeClaimTemplates:
  - metadata:
      name: service-name-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "standard"
      resources:
        requests:
          storage: 1Gi

 

3. ReplicaSet

  • Purpose: 동일 클러스터 내 동일한 파드들을 원하는 숫자만큼 유지하기 위해 사용하여 배포 순서가 중요하지 않은 stateless 어플리케이션 배포 및 스케일링에 이용한다. maintain a desired number of identical pods in the cluster, ensuring high availability and fault tolerance. scale and manage stateless applications where the order of pod creation and termination does not matter. useful to ensure a specific number of replicas are running, regardless of the underlying nodes' availability.
  • Selector and Labels: 관리할 파드를 구별하기 위해 보통 label selector을 이용하며 매칭되는 라벨을 가진 파드가 명시된 숫자만큼 항상 실행되도록 관리할 수 있다. it uses a label selector to identify the pods it needs to manage, and ensures the specified number of pods with matching labels are always running.
  • Pod Template: 파드 업데이트 및 새 파드를 생성할 때 파드 템플릿을 이용한다. 즉 새로운 변경을 포함하여 업데이트시 해당 변경된 템플릿을 참조하여 새 파드가 생성된다. updating the pod template will apply the changes to the ReplicaSet and it'll create new pods based on the updated template.
  • Automatic Scaling: 스케일 업 시, 해당 리플리카 숫자 만큼 쿠버네티스에 의해 파드가 증가된다. 또한 리플리카 수를 더 작게 변경하면 존재하던 파드 중 일부가 종료되어 해당 숫자만큼 줄어든다.

4. Job: 데이터 처리 및 백업같은 수명이 짧은 배치성 jobs 에 쓰인다. used for short-lived tasks or batch jobs that run to completion such as data processing or backups.

예시: 크론 잡 만들기 an example command to create a cronjob

kubectl create cronjob my-cronjob --image=my-image:latest --schedule="* * * * *"

일반 job 생성 creating a typical job

kubectl create job my-job --image=my-image:latest

 

 

 

-. kubectl 명령어를 이용한 파드 재시작(재배포) 방법

 

1. Restarting a Pod:

단일 파드를 재시작하는 방법은 단순하게 running중인 현재의 pod를 삭제하여 연결된 replica 정의에 따라 새로 자동 생성되도록 하는 방법이 있다.

# Replace "your-pod-name" with the name of your pod
kubectl delete pod your-pod-name

 

2. Restarting a Deployment:

또한 좀더 stateful 한 서비스를 위해 점진적인 배포 및 재시작을 원하는 경우 rollout을 사용하면 된다.

kubectl rollout restart deployment your-deployment-name

 

3. Restarting a StatefulSet:

마찬가지로 statefulset으로 정의된 배포에 대하여 점진적인 롤아웃 방식 재 배포를 원하는 경우 아래와 같이 하면 된다.

kubectl rollout restart statefulset your-statefulset-name

4. Restarting a DaemonSet:

  • Rolling update

쿠버네티스 버전 1.5 와 그 이전 버전은 데몬셋 템플릿을 수정하여 업데이트 시, 매뉴얼하게 직접 데몬셋 파드를 삭제하여 새 파드가 생성되는 on Delete 방식이며, 1.6부터는 디폴트로 롤링 업데이트를 사용할 수 있는 것으로 공식 문서에 기재되어 있다. (롤링 업데이트: 템플릿 수정시 이전 수정 전 파드들이 자동 종료되고 새 버전 템플릿을 반영한 새 파드들이 생성되는 방식)

롤링 업데이트를 사용하려면 DaemonSet 템플릿에 아래 부분을 명시한다.

.spec.updateStrategy.type to RollingUpdate

Any updates to a RollingUpdate DaemonSet ".spec.template" will trigger a rolling update. you can update the DaemonSet by applying a new YAML file.

 

공식문서 참조: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/

 

Perform a Rolling Update on a DaemonSet

This page shows how to perform a rolling update on a DaemonSet. Before you begin You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run this tutorial on a clust

kubernetes.io

 

  • Cascading deletion

공식문서 참조: https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/

 

Use Cascading Deletion in a Cluster

This page shows you how to specify the type of cascading deletion to use in your cluster during garbage collection. Before you begin You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluste

kubernetes.io

& foreground, background cascading deletion: https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/

 

Use Cascading Deletion in a Cluster

This page shows you how to specify the type of cascading deletion to use in your cluster during garbage collection. Before you begin You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluste

kubernetes.io

 

리소스를 삭제 시 해당 리소스 및 리소스와 연관된 리소스 (configmap 등)를 함께 삭제하는 것과 관련된 것이며 이 때, foreground 또는 background 로 진행할지 사전 정의가 가능하다. 디폴트는 foreground이며 background 삭제는 opt-in 옵션이다.

When you delete a DaemonSet using the kubectl delete command without the --cascade=false flag or simply use kubectl delete daemonset your-daemonset-name, Kubernetes will perform a cascading delete by default. This means that not only the DaemonSet resource will be deleted, but also all the pods managed by that DaemonSet will be terminated.

 

Issue example:

Reason:         Evicted
Message:        Pod The node had condition: [DiskPressure].

 

멀쩡하게 running 중이던 Pod 의 상태가 Evicted 로 여러 Pod로 늘어나 있는 경우, 어떤 이유에 의해 새  Pod를 예약할 수 없는 상태일 때 발생한다.

여기서 Message 를 보면 DiskPressure 조건에 의해 실패하였으며 해당 경우에는 노드의 사용 가능한 디스크 공간이 부족하거나 소진되어 쿠버네티스 시스템에서 해당 노드에 새 포드를 예약할 수 없어 포드가 해당 노드에서 제거된 것을 알 수 있다.

시스템은 디스크 공간을 확보하고 클러스터의 전반적인 안정성을 보장하기 위해 노드의 기존 포드를 제거할 수 있다.

 

해당 DiskPressure 조건에 미치려면 몇가지 경우의 수가 있다.

  1. 해당 노드의 disk usage 문제
    1. 노드의 디스크 공간 체크, 부족시 불필요한 파일 삭제 및 더 많은 스토리지 용량 추가 등으로 해결
  2. 해당 노드의 사용중인 inode usage 문제
    1. df -i 로 inode 용량 확인
  3. 처리되는 파일 갯수의 문제 (Max open files)
    1. 아래 명령어로 확인
cat /proc/$(pgrep kubelet)/limits | grep "Max open files"

             결과 값:

# cat /proc/$(pgrep kubelet)/limits | grep "Max open files"
Max open files            1000000              1000000              files

            2. 높은 경우, kubelet 프로세스의 최대 열린 파일 수를 늘려본다. 해당 노드의 kubelet conf 파일에 적절한 Limit 값을 설정하면 된다.

                설정 파일 위치: /etc/systemd/system/kubelet.service.d/

                추가 값 예시: LimitNOFILE=1000000

[Service] 섹션에 해당 값을 추가한다. 추가 후에는 데몬을 리로드하고 kubelet 을 재기동한다.

sudo systemctl daemon-reload
sudo systemctl restart kubelet

kubelet 의 eviction threshold 를 확인하려면 해당 워커노드의 /etc/kubernetes/ 에 kubelet 관련 파일의 "evictionHard" 부분을 확인할 수 있다.

  "evictionHard": {
    "memory.available": "100Mi",
    "nodefs.available": "10%",
    "nodefs.inodesFree": "5%"
  },

nodefs.available은 disk pressure과 관련있고 위에서는 10%로 설정되어있다. 즉, 해당 노드에서 사용 가능한 파일 시스템 공간의 비율이 10% 미만으로 떨어지면 Kubernetes가 노드에서 포드를 evicted한다.

 

공식문서 참고:

Minimum eviction reclaim

In some cases, pod eviction only reclaims a small amount of the starved resource. This can lead to the kubelet repeatedly hitting the configured eviction thresholds and triggering multiple evictions.

You can use the --eviction-minimum-reclaim flag or a kubelet config file to configure a minimum reclaim amount for each resource. When the kubelet notices that a resource is starved, it continues to reclaim that resource until it reclaims the quantity you specify.

For example, the following configuration sets minimum reclaim amounts:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
  memory.available: "500Mi"
  nodefs.available: "1Gi"
  imagefs.available: "100Gi"
evictionMinimumReclaim:
  memory.available: "0Mi"
  nodefs.available: "500Mi"
  imagefs.available: "2Gi"

 

이외 기존 Evicted Pod들을 아래 명령어로 Running 상태인 pod 제외하고 제거할 수 있다.

kubectl get pods -n <namespace> --field-selector=status.phase=Failed | grep Evicted | awk '{if($3!="Running") print $1}' | xargs kubectl delete pod -n <namespace>

또는 깔끔하게 해당 포드의 deployment 파일 replica 수롤 조정하여 재 배포한다.

replicas 를 0개로 했다가 다시 증가시킨다.

kubectl scale deployment <your-deployment-name> --replicas=0 -n monitoring

재 배포 전에 Back-off 에러가 발생하여 로그를 확인해보니 아래 에러가 발생하였다.

msg="Error loading config (--config.file=/etc/config/prometheus.yml)" err="parsing YAML file /etc/config/prometheus.yml: yaml: unmarshal errors:\n  line 14: field metrics_path not found in type struct { Targets []string \"yaml:\\\"targets\\\"\"; Labels model.LabelSet \"yaml:\\\"labels\\\"\" }"

컨테이너 두개중 컨피그맵을 통째로 /etc/config 에 맵핑한 것은 정상인데 두번째 컨테이너의 /etc/config/blahblah.yml 로 마운트한 부분 값과 관련하여 yaml: unmarshal 에러가 발생했다.

관련 서비스 컨피그맵의 해당 yml 아래 metrics_path 를 확인하여 syntax 에러를 수정하고 재 배포 후 해결되었다.

 

Before:

      - job_name: actuator
        static_configs:
          - targets: [eap-was.eap.svc:30001]
            metric_path: '/actuator/prometheus'

After: (metrics_path 위치 변경)

- job_name: actuator
  metrics_path: /actuator/prometheus
  static_configs:
  - targets:

 

이외 추가로 알게된 Tip:

  • DaemonSet YAML 을 이전 generation 버전으로 롤백하려고 할때 -

1. 롤백 가능한 버전을 아래 명령어를 이용해 확인한다.

kubectl rollout history daemonset <daemonset-name> -n <namespace>

2. 해당 원하는 버전으로 롤백한다.

kubectl rollout undo daemonset <daemonset-name> -n <namespace> --to-revision=1

--to-revision 에 원하는 버전 값을 입력할 수 있다.

 

  • 기존 중복된 리소스로 인해 helm install 이 실패시 

에러 메시지 예:

helm install <serviced> <service>/<serviced>  --namespace <your namespace>
Error: INSTALLATION FAILED: rendered manifests contain a resource that already exists. Unable to continue with install: ClusterRoleBinding "serviced" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation

해당 리소스 삭제 후 재 설치한다.

kubectl delete clusterrolebinding <servicd name> -n <your namespace>

 

Pod selection for kubelet eviction: https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/

 

Node-pressure Eviction

Node-pressure eviction is the process by which the kubelet proactively terminates pods to reclaim resources on nodes. The kubelet monitors resources like memory, disk space, and filesystem inodes on your cluster's nodes. When one or more of these resources

kubernetes.io

Pod selection for kubelet eviction 
If the kubelet's attempts to reclaim node-level resources don't bring the eviction signal below the threshold, the kubelet begins to evict end-user pods.
The kubelet uses the following parameters to determine the pod eviction order:
Whether the pod's resource usage exceeds requestsPod PriorityThe pod's resource usage relative to requests
As a result, kubelet ranks and evicts pods in the following order:
BestEffort or Burstable pods where the usage exceeds requests. These pods are evicted based on their Priority and then by how much their usage level exceeds the request.Guaranteed pods and Burstable pods where the usage is less than requests are evicted last, based on their Priority.
Note: The kubelet does not use the pod's QoS class to determine the eviction order. You can use the QoS class to estimate the most likely pod eviction order when reclaiming resources like memory. QoS does not apply to EphemeralStorage requests, so the above scenario will not apply if the node is, for example, under DiskPressure.

 

+

Node conditions 

The kubelet reports node conditions to reflect that the node is under pressure because hard or soft eviction threshold is met, independent of configured grace periods.

The kubelet maps eviction signals to node conditions as follows:

 

ETC.

kube-controller-manager.service

ExecStart=/usr/local/bin/kube-controller-manater \\
	--address=0.0.0.0 \\
    --cluster-cidr=x.x.x.x/x \\
    --cluster-name=<name> \\
    ....
    
    --node-monitor-period=5s
    --node-monitor-grace-period=40s
    --pod-eviction-timeout=5m0s
    
    ...

 

 

 

키바나를 배포했는데 별다른 에러 로그 없이 계속 probe check failed 가 나는 상황에, 실제 파드(포드) 안에서는 서비스 포트(port: 5601)로 정상 응답 확인되며 포드 밖에서는 사설아이피로 방화벽이 모두 허용되있으며 배포된 pod 아이피의 해당 포트 및 서비스 uri로 connection refused가 나는 상황이면,

컨피그맵(kibana-config로 생성했다.)으로 마운트된 kibana.yml 에 server.host: "0.0.0.0" 을 추가 및 배포하여 이를 해결할 수 있다.

pod description (에러 상황): dial tcp x.x.x.x:5601 connect: connection refused

키바나 내부 포드(pod)에 들어가 본다.

kubectl exec -it <pod name> -n <your namespace> -- /bin/bash

들어가면 호스트네임이 보이지만 확인차 hostname 명령어를 쳐서 확인할 수도 있다. (여기서는 hostname: kibana-0)

pod 안에서 호스트네임으로 요청 시 connection refused
pod 안에서 localhost로 요청시 정상 응답

[해결 resolution]

kubectl edit cm kibana-config -n <your namespace>
apiVersion: v1
data:
  kibana.yml: |
    server.host: "0.0.0.0"

위 세팅으로 새로 배포시 이제는 포드 안에서 호스트 네임으로 요청해도 localhost 요청시와 같이 동일하게 정상 응답이 반환되며, 지정한 로드밸런서 타겟그룹에도 아이피가 자동 등록되어 healthy 상태로 확인되었다.

pod 안에서 호스트네임으로 요청 시 정상 응답 반환
Ready 1/1 로 정상 running 상태의 pod 확인

 

문제 해설:

localhost:5601로 로컬 호스트에서 Kibana에 액세스할 수 있지만 kibana-0:5601로는 외부에서 액세스할 수 없는 상태입니다. kibana-0는 호스트 네임이고 배포시 정한 이름입니다. 

이는 Kibana가 동일한 시스템의 연결만 허용하는 루프백 인터페이스에서만 수신(listening)하기 때문일 수 있습니다.

sudo netstat -tlnp | 명령을 실행하여 Kibana가 수신 대기 중인 인터페이스를 확인할 수 있습니다. 포드 내부의sudo netstat -tlnp | grep 5601을 하여 Kibana가 127.0.0.1에서만 수신하는 경우 모든 인터페이스(0.0.0.0) 또는 포드에 액세스하는 데 사용하는 특정 인터페이스에서 수신하도록 구성을 수정해야 합니다.

모든 인터페이스에서 수신 대기하려면 kibana.yml 구성 파일을 수정하고 server.host 옵션을 0.0.0.0으로 설정하면 됩니다. 이렇게 변경한 후 구성을 적용하려면 Kibana를 다시 시작해야 합니다.



It seems that you are able to access Kibana on the local host with localhost:5601, but not from the outside with kibana-0:5601. This could be because Kibana is only listening on the loopback interface, which only allows connections from the same machine.

You can check which interfaces Kibana is listening on by running the command sudo netstat -tlnp | grep 5601 inside the pod. If Kibana is only listening on 127.0.0.1, then you will need to modify its configuration to listen on all interfaces (0.0.0.0) or the specific interface that you are using to access the pod.

To listen on all interfaces, you can modify the kibana.yml configuration file and set the server.host option to 0.0.0.0. For example:After making this change, you will need to restart Kibana for the configuration to take effect.

 

만약 어떤 조정을 위해서 배포될 pod 안의 /etc/sysctl.conf 값을 변경하고 싶은데 read-only filesystem 이라고 로그 확인되면서 배포 커맨드가 적용되지 않는 경우, 그러나 배포 시마다 새로운 pod에 해당 값을 고정으로 적용이 필요한 경우,

컨피그맵으로 해당 값 매칭하여 볼륨 마운트 추가 하는 방법이 가능하다.

 

컨피그맵 생성 예시 (명령어 혹은 yaml 배포 이용):

apiVersion: v1
kind: ConfigMap
metadata:
  name: sysctl-cm
data:
  sysctl.conf: |
    net.ipv6.conf.all.disable_ipv6=1

FYI it's possible that the established IPv6 connections were created before the net.ipv6.conf.all.disable_ipv6 sysctl option was set. The sysctl option disables the IPv6 protocol on the network interface, but it doesn't necessarily terminate existing connections.

Additionally, some applications may still try to establish IPv6 connections even if it's disabled on the network interface. This can be due to the application's configuration or the way it's programmed.

 

배포 yaml 파일 Deployment 항목(pod배포 항목)의 spec, 컨테이너 밑의 volumeMounts에 추가한다.

          volumeMounts:
            - name: sysctl-conf
              mountPath: "/etc/sysctl.conf"
              subPath: sysctl.conf

 

마운트할 대상 볼륨의 컨피그 맵 정의를 volumes 밑에 추가한다.

 

      volumes:
        - name: sysctl-conf
          configMap:
            name: sysctl-cm
            items:
              - key: sysctl.conf
                path: sysctl.conf

 

참고로 yaml 배포시 커맨드를 사용하여 무언가 설치하고 값을 추가하려는데 권한이 없어 안된다는 에러를 접하면,

runAsUser을 0 로 설정하여 최상위 권한으로 설정배포 가능하다.

 

예시:

스펙의 컨테이너 이미지 부분 밑에 추가하였다.

          securityContext:
            runAsUser: 0

커맨드 예시:

               command:                
               - /bin/bash
               - -c
               - apk update && apk add sudo && sysctl -w net.ipv6.conf.all.disable_ipv6=1 && sleep infinity

커맨드는 [] 묶음으로도 표현 가능하다.

command: ["/bin/bash", "-c", "echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.conf && sysctl -p && sleep infinity"]
    securityContext:
      privileged: true

여기서 privileged: true 는 모든 기능으로 포드를 실행하고 읽기 전용 파일 시스템을 우회하는 옵션이다.

option to run the pod with all capabilities and bypass the read-only file system.

 

위 과정을 거쳐 컨피그 맵을 생성하고 볼륨 마운트를 해서, 직접 포드 안에 들어가 해당 값이 적용된 것을 확인할 수 있다.

kubectl exec -it <your pod name> -n <your namespace> -- /bin/bash
bash-5.1# cat /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6=1

 

또한 로드밸런서(nlb)의 타겟그룹이 ipv6가 아닌 ipv4만 체크하도록 설정하려면 아래 설정을 배포 yaml 파일에 추가한다.

 

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: tcp
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080" # replace with the port used by your application
spec:
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 8080 # replace with the port used by your application
    targetPort: 8080 # replace with the port used by your application
  type: LoadBalancer

 

여기에 아래와 같이 추가로 원하는 설정을 입력할 수 있다.

service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: "/healthcheck"

service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: ?

 

In this example, the health check protocol is set to TCP, which means that the target group will only check IPv4. You can also specify the health check path and timeout, if needed, using the service.beta.kubernetes.io/aws-load-balancer-healthcheck-path and service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout annotations.

 

why the connection status of ipv6 keeps changing from established to time_wait?

In general, when a TCP connection is closed, it enters a TIME_WAIT state to ensure that all packets have been received by the other end. During this state, the connection is closed, but the socket is still bound to the local and foreign IP addresses and ports.

In the case of IPv6, the addresses used are often based on temporary interface identifiers that are periodically regenerated by the system to protect the privacy of the user. When a new identifier is generated, existing TCP connections using the old identifier are closed, which can result in a large number of TIME_WAIT connections.

To address this issue, some operating systems provide a feature called "stable privacy addresses" that maintain a stable identifier for the network interface, even if the temporary identifier changes. This can help prevent TIME_WAIT connections from being created when the temporary identifier changes.

Additionally, you may want to check if there are any network or firewall issues that could be causing the TCP connections to be closed unexpectedly or prematurely, as this can also lead to TIME_WAIT connections.

 

+ Recent posts