EKS에서 보통 EKS 노드가 생성될 때 bootstrap 스크립트를 통해 kubelet arguments를 설정할 수 있고, keep-alive 관련 수정을 원하는 경우 '--allowed-unsafe-sysctls' 파라미터를 포함하는 kubelet을 기동하는 node group을 생성하여 원하는 작업을 수행한다.

 

우선 아래 github link를 통해 eks 노드가 생성될때 각 설정에 대해 참고할 수 있다.

https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh

 

GitHub - awslabs/amazon-eks-ami: Packer configuration for building a custom EKS AMI

Packer configuration for building a custom EKS AMI - GitHub - awslabs/amazon-eks-ami: Packer configuration for building a custom EKS AMI

github.com

또한 아래 링크에서 EKS(eksctl) Config 파일 설정에 대해 각 항목을 참고할 수 있다.

https://eksctl.io/usage/schema/#nodeGroups-overrideBootstrapCommand

 

Config file schema - eksctl

Config file schema Use eksctl utils schema to get the raw JSON schema.

eksctl.io

제목에 따라 EKS pod에 keep alive 관련 설정을 하려면 먼저 Custom AMI를 지정하고,

eksctl config file 설정 중 overrideBootstrapCommand 설정을 통해 bootstrap script를 지정하여

--allowed-unsafe-sysctls 파라미터가 설정된 kubelet 을 기동하는 노드 그룹을 생성한다.

 

 

pod.yaml 예시

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command: ["sleep"]
    args: ["1d"]
  securityContext:
    sysctls:
    - name: net.ipv4.tcp_keepalive_intvl
      value: "60"

eksctl-config.yaml 예시

 

apiVersion: eksctl.io/v1alpha5 
kind: ClusterConfig

metadata:
  name: <cluster name>
  region: <region>

managedNodeGroups:
- name: <nodegroup name>
  ami: <ami id>
  amiFamily: AmazonLinux2
  minSize: 0
  maxSize: 10
  desiredCapacity: 2
  ssh:
    allow: true
    publicKeyName: <public key>
  overrideBootstrapCommand: |
    #!/bin/bash
    set -ex
    /etc/eks/bootstrap.sh <cluster name> --kubelet-extra-args "--node-labels=alpha.eksctl.io/cluster-name=<cluster name>,alpha.eksctl.io/nodegroup-name=<nodegroup-name>,eks.amazonaws.com/nodegroup=<nodegroup-name>,eks.amazonaws.com/nodegroup-image=<ami  id> --allowed-unsafe-sysctls 'net.ipv4.tcp_keepalive_intvl'"

 

kubectl 명령어로 설정된 값을 확인한다.

$ kc exec -it ubuntu -- sysctl -a | grep -i keepalive
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200

 

추가 참고 자료:

쿠버네티스에서 sysctl 이용하기: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/

개발팀으로부터 cloudon 네임스페이스에 있는 cloudon-ingress를 삭제하려고 하는데 권한오류로 삭제가 안되어서 재배포가 안된다고 요청이 왔다.

에러 메시지는 다음과 같다.

 

Error Message : 
{"level":"error","ts":xxxxxxxx.xxxxxx,"logger":"controller.ingress","msg":"Reconciler error","name":"cloudon-ingress","namespace":"cloudon","error":"AccessDenied: User: arn:aws:sts::[account id]:assumed-role/AmazonEKSLoadBalancerControllerRole/xxxxxxxxxxxxx is not authorized to perform: elasticloadbalancing:DeleteLoadBalancer on resource: arn:aws:elasticloadbalancing:[region]:[account id]:loadbalancer/app/xxxxxx-cloudon-cloudonin-xxxx/xxxxxxxxxxxx because no identity-based policy allows the elasticloadbalancing:DeleteLoadBalancer action\n\tstatus code: 403, request id: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"}

 

 

확인해보니 해당 역할 신뢰관계에 해당 EKS 클러스터의 OIDC 네임스페이스가 특정 네임스페이스만 명시적으로 sts 액션이 허용되어있어, cloudon 네임스페이스를 추가하였다.

 

        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::[account id]:oidc-provider/oidc.eks.[region].amazonaws.com/id/[eks oidc id]"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.[region].amazonaws.com/id/[eks oidc id]:sub": "system:serviceaccount:cloudon:aws-load-balancer-controller",
                    "oidc.eks.[region].amazonaws.com/id/[eks oidc id]:aud": "sts.amazonaws.com"
                }
            }
        }

 

허용 후 바로 해결되었다.

 

kubectl을 이용해 cloudwatch agent 배포후 해당 pod 가 이미지 pull에 실패해 backoff 된것을 확인했다.

 

아래 명령어를 사용해서 에러 원인이 추정 가능했다.

 

kubectl describe pod cloudwatch-agent-xxxx -n amazon-cloudwatch

Scheduled -> Pulling -> Failed -> BackOff

Error: ErrImagePull
Error: ImagePullBackOff

 

해당 에러메시지가 있는 화면에서 Scheduled Message Event의 ip-xx-xx-xxx-xxx.ap-northeast-1.compute.internal 부분을 확인하면 어떤 인스턴스의 ENI가 네트워킹에 사용되었는지 확인가능하고, 해당 EKS 인스턴스의 서브넷에 443 port 연결 허용 및 라우팅 추가 후 위에 이용된 ENI에 임시로 ENI를 붙여 인터넷이 되게 하여 이미지 풀이 가능하게 한다.

그다음 작업과 관련된 해당 pod를 삭제하면 스케줄링에 의해 새로운 pod가 배포되며 이미지를 가져와서 running상태로 바뀐다.

 

kubectl delete pod cloudwatch-agent-fz4hj -n amazon-cloudwatch

작업한 pod를 삭제 후 다시 해당 네임스페이스에 get pod 하면 새로운 pod가 배포중인 것이 확인된다.

kubectl get pod -n amazon-cloudwatch

위에서는 cloudwatch-agent-pdklg pod가 새로 배포되었다.

 

해당 EKS pod의 private 한 연결 상태를 유지하고 이미지를 배포하길 바란다면 아래 방법을 이용해보자.

 

To download a container image from public server(public ec2) and then deploy it to a pod in a private EKS cluster (private pod), you can follow these general steps:

  1. Connect to the public EC2 instance and use a command-line tool like Docker or Podman to download the container image that you want to deploy.

For example, if you're using Docker, you can use the following command to download an image from Docker Hub:

docker pull <image-name>
  1. After downloading the image, you can save it to a file using the Docker save command. This will create a tar archive of the image and its dependencies that you can transfer to another machine.
docker save <image-name> > <image-file>.tar
  1. Transfer the image file to a machine that has access to your private EKS cluster. You can use tools like SCP or AWS S3 to transfer the file.
  2. On the machine that has access to the EKS cluster, use the Docker load command to load the image from the file.
docker load < <image-file>.tar
  1. After loading the image, you can create a Kubernetes deployment or pod definition that references the new image. You can use the kubectl apply command to apply the configuration.
kubectl apply -f <deployment-or-pod-definition>.yaml

Note that to deploy a container image to a private EKS cluster, you will need to have the necessary credentials and permissions to access the EKS cluster and deploy the image. You may also need to configure network settings to allow the pod to access any required resources, such as databases or other services.

 

========================================================

명령어 메모:

특정 네임스페이스에 pod 생성:

kubectl run <POD_NAME> --image=<IMAGE_NAME> --namespace=<NAMESPACE_NAME>

모든 네임스페이스에 대한 pod 확인:

kubectl get pods --all-namespaces

kubectl get pods -A

 

First of all - TCP provides reliable end to end data transfer. 

It can easily enhanced at the application layer with SSL to provide security services,

and guaranteeing that all data will eventually get to it's destination.

electronic mail(SMTP), remote terminal access(Telnet), web(HTTP), and File transfer(FTP) applications are using TCP most likely.

Streaming multimedia (HTTP, RTP-real time transfer protocol) applications are using TCP or UDP,

Internet telephone - loss tolerant - application  typically is using UDP.

 

 

In earnest, congestion control and flow control are two important mechanisms in TCP (Transmission Control Protocol) that help regulate the flow of data between two endpoints in a network. Here's a brief description of each:

  1. Congestion control: This mechanism is used to prevent network congestion by slowing down the rate at which data is transmitted when the network is congested. It is based on the idea of monitoring the network for signs of congestion and then adjusting the transmission rate accordingly. TCP implements congestion control by using a combination of techniques, including slow start, congestion avoidance, and congestion recovery.
  • Slow start: In the beginning of a transmission, TCP starts by sending a small number of packets and then gradually increases the transmission rate until it detects signs of congestion.
  • Congestion avoidance: Once congestion is detected, TCP reduces the transmission rate to avoid further congestion.
  • Congestion recovery: If packets are lost or dropped due to congestion, TCP uses a mechanism called fast retransmit/fast recovery to quickly recover from the loss and resume normal transmission.
  1. Flow control: This mechanism is used to prevent the receiver from being overwhelmed by too much data. It is based on the idea of regulating the flow of data from the sender to the receiver. TCP implements flow control by using a sliding window protocol.
  • Sliding window protocol: The receiver informs the sender about how much data it can receive by sending a window size value. The sender then sends data up to that window size and waits for an acknowledgement from the receiver before sending more data.

By implementing both congestion control and flow control, TCP ensures that data is transmitted efficiently and reliably between two endpoints in a network.

 

혼잡 제어 및 흐름 제어는 네트워크의 두 끝점 사이의 데이터 흐름을 조절하는 데 도움이 되는 TCP(전송 제어 프로토콜)의 두 가지 중요한 메커니즘입니다. 각각에 대한 간략한 설명은 다음과 같습니다.

혼잡 제어: 이 메커니즘은 네트워크가 혼잡할 때 데이터 전송 속도를 늦춤으로써 네트워크 혼잡을 방지하는 데 사용됩니다. 정체의 징후에 대해 네트워크를 모니터링한 다음 그에 따라 전송 속도를 조정한다는 아이디어를 기반으로 합니다. TCP는 느린 시작, 혼잡 회피, 혼잡 복구 등의 기술 조합을 사용하여 혼잡 제어를 구현합니다.
느린 시작: 전송이 시작될 때 TCP는 적은 수의 패킷을 보내는 것으로 시작한 다음 혼잡의 징후를 감지할 때까지 점차적으로 전송 속도를 높입니다.
혼잡 회피: 혼잡이 감지되면 TCP는 추가 혼잡을 피하기 위해 전송 속도를 줄입니다.
혼잡 복구: 혼잡으로 인해 패킷이 손실되거나 누락된 경우 TCP는 빠른 재전송/빠른 복구라는 메커니즘을 사용하여 손실을 신속하게 복구하고 정상적인 전송을 재개합니다.
흐름 제어: 이 메커니즘은 수신자가 너무 많은 데이터에 압도당하는 것을 방지하는 데 사용됩니다. 발신자에서 수신자로의 데이터 흐름을 규제한다는 아이디어를 기반으로 합니다. TCP는 슬라이딩 윈도우 프로토콜을 사용하여 흐름 제어를 구현합니다.
슬라이딩 윈도우 프로토콜: 수신자는 윈도우 크기 값을 전송하여 수신할 수 있는 데이터의 양을 발신자에게 알려줍니다. 그런 다음 보낸 사람은 해당 창 크기까지 데이터를 보내고 더 많은 데이터를 보내기 전에 받는 사람의 승인을 기다립니다.
혼잡 제어와 흐름 제어를 모두 구현함으로써 TCP는 데이터가 네트워크의 두 끝점 간에 효율적이고 안정적으로 전송되도록 합니다.

UDP (User Datagram Protocol) and TCP (Transmission Control Protocol) are two widely used protocols in computer networking. While both protocols are used to send data over a network, there are some key differences between them. Here are the main differences between UDP and TCP:

  1. Connection-oriented vs Connectionless: TCP is a connection-oriented protocol, meaning it establishes a connection between the two endpoints before sending data. UDP, on the other hand, is connectionless, meaning data is sent without any prior communication or connection setup.
  2. Reliability: TCP is designed to be reliable and ensures that all data is delivered to the destination in the correct order. It uses error detection and correction mechanisms to ensure that data is not lost or corrupted during transmission. UDP, on the other hand, does not have these mechanisms, and some data packets may be lost or arrive out of order.
  3. Speed: UDP is generally faster than TCP because it does not have to establish a connection or perform error detection and correction. This makes it a good choice for applications that require fast data transmission, such as online gaming or video streaming.
  4. Data size: TCP is better suited for larger data transmissions, as it can handle larger amounts of data without loss or corruption. UDP, on the other hand, is better suited for smaller data transmissions, such as sending sensor data or real-time voice communication.

In summary, TCP is a reliable, connection-oriented protocol that is better suited for larger data transmissions, while UDP is a faster, connectionless protocol that is better suited for smaller data transmissions that require low latency.

 

UDP(사용자 데이터그램 프로토콜) 및 TCP(전송 제어 프로토콜)는 컴퓨터 네트워킹에서 널리 사용되는 두 가지 프로토콜입니다. 두 프로토콜 모두 네트워크를 통해 데이터를 전송하는 데 사용되지만 두 프로토콜 사이에는 몇 가지 중요한 차이점이 있습니다. UDP와 TCP의 주요 차이점은 다음과 같습니다.

연결 지향(connection oriented) vs 비연결(connectionless): TCP는 연결 지향 프로토콜입니다. 즉, 데이터를 보내기 전에 두 엔드포인트 간에 연결을 설정합니다. 반면 UDP는 연결이 없습니다. 즉, 사전 통신이나 연결 설정 없이 데이터가 전송됩니다.

신뢰성(reliable): TCP는 신뢰할 수 있도록 설계되었으며 모든 데이터가 올바른 순서로 대상에 전달되도록 합니다. 오류 감지 및 수정 메커니즘을 사용하여 전송 중에 데이터가 손실되거나 손상되지 않도록 합니다. 반면 UDP에는 이러한 메커니즘이 없으며 일부 데이터 패킷이 손실되거나 순서 없이 도착할 수 있습니다.

속도: UDP는 연결을 설정하거나 오류 감지 및 수정을 수행할 필요가 없기 때문에 일반적으로 TCP보다 빠릅니다. 따라서 온라인 게임이나 비디오 스트리밍과 같이 (real-time applications can often tolerate loss) 빠른 데이터 전송이 필요한 애플리케이션에 적합합니다.

(그러나 많은 방화벽이 UDP를 막아서 웹디자이너들이 멀티미디어나 실시간 어플리케이션을 TCP로 전송하도록 고안하기도 합니다.)

데이터 크기: TCP는 손실이나 손상 없이 더 많은 양의 데이터를 처리할 수 있으므로 더 큰 데이터 전송에 더 적합합니다. 반면에 UDP는 센서 데이터 전송 또는 실시간 음성 통신과 같은 소규모 데이터 전송에 더 적합합니다.

요약하면 TCP는 더 큰 데이터 전송에 더 적합한 신뢰할 수 있고 연결 지향적인 프로토콜인 반면, UDP는 짧은 대기 시간이 필요한 더 작은 데이터 전송에 더 적합한 더 빠르고 비연결적인 프로토콜입니다.

A checksum is a value calculated from a set of data that is used to detect errors that may have occurred during data transmission or storage.

It is typically a simple algorithm that calculates a unique value from the data, which can then be compared to the checksum generated by the receiver to determine whether the data has been corrupted or altered.

 

A parity bit is a type of checksum used to detect errors in data transmission or storage. It is a single bit of data that is added to a group of bits to make the total number of 1s in the group either even or odd. The parity bit is then used by the receiver to determine whether the data has been transmitted correctly or not.

 

The key difference between checksum and parity bit is that checksum involves calculating a unique value from a set of data, while parity bit involves adding a single bit of data to a group of bits to make the total number of 1s either even or odd. Checksums can be more complex and can detect a wider range of errors than parity bits, but they are also more computationally intensive. Parity bits, on the other hand, are simpler and require less computational power, but they can only detect certain types of errors.

 

체크섬은 데이터 전송 또는 저장 중에 발생할 수 있는 오류를 감지하는 데 사용되는 데이터 세트에서 계산된 값입니다.

일반적으로 데이터에서 고유한 값을 계산하는 간단한 알고리즘으로, 수신자가 생성한 체크섬과 비교하여 데이터가 손상되었거나 변경되었는지 확인할 수 있습니다.



패리티 비트는 데이터 전송 또는 저장 오류를 감지하는 데 사용되는 일종의 체크섬입니다.(checksum type) 그룹의 총 1 수를 짝수 또는 홀수로 만들기 위해 비트 그룹에 추가되는 단일 비트의 데이터입니다. 그런 다음 패리티 비트는 데이터가 올바르게 전송되었는지 여부를 결정하기 위해 수신기에서 사용됩니다.



체크섬과 패리티 비트의 주요 차이점은 체크섬은 데이터 세트에서 고유한 값을 계산하는 반면 패리티 비트는 비트 그룹에 데이터의 단일 비트를 추가하여 1의 총 수를 짝수 또는 홀수로 만드는 것입니다. 체크섬은 더 복잡할 수 있고 패리티 비트보다 더 넓은 범위의 오류를 감지할 수 있지만 계산 집약적이기도 합니다. 반면에 패리티 비트는 더 간단하고 계산 능력이 덜 필요하지만 특정 유형의 오류만 감지할 수 있습니다.

 

 

OSI 7 Layers and TCP/IP 5 Layers

 

Definition of Network Units: messsage, segment, datagram, frame

 

 

먼저 각 레이어에 대해 기억하자.

 

1. Application Layer

프로토콜: HTTP, FTP, SMTP..

데이터 유닛: message

 

2. Presentation Layer

프로토콜: SSL/TLS, MIME (Multipurpose Internet Mail Exensions)..

 

 

3. Session Layer

프로토콜: NetBIOS (Network Basic Input/Output System), NFS (Network File System),..

 

4. Transport Layer

프로토콜: TCP, UDP..

데이터 유닛: segment

 

5. Network Layer

프로토콜: IP, ICMP..

데이터 유닛: datagram

 

6. Data Link Layer

프로토콜: ARP(Address Resolution Protocol), PPP (Point-to-Point Protocol)..

데이터 유닛: frame

 

6. Physical Layer

프로토콜: Ethernet, Token Ring, FDDI...

 

From Wikipedia

 

 

 

아래 가이드대로 설정해도 aurora mysql RDS 이용시 제대로 작동하지 않아, 

( RDS를 7일 이상 Stop 할때 가이드: https://aws.amazon.com/premiumsupport/knowledge-center/rds-stop-seven-days/?nc1=h_ls )

RDS 옵션 확인시 인스턴스는 stop옵션이 존재하지 않고 클러스터에 있는 것을 확인하여 - 해당 샘플 코드에서

인스턴스를 클러스터로 할 수 있도록 변경하였다.

참고 문서는 아래 API 문서를 참고하였고 실제 api 호출시 나오는 로그의 항목 필드를 확인해서 필터링할 수 있는지 봐서

코드를 변경하였다.

Python boto3 API 문서: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_instances

RDS는 7일마다 자동시작되므로 cron(00 00 ? * 5 *) Event 트리거를 추가하였고, 시간과 분은 직접 stop한 시각으로부터 +RDS 시작에 걸리는 시간(분) 뒤로 적절히 정하였다.

 

아래 에러코드 발생시에는 DB 인스턴스에 추가한 태그 (여기서는 autostop=yes) 를 삭제하고, 

DB 클러스터를 선택하여 RDS 클러스터 태그로 추가한다.

Cannot stop instance blahblah.
An error occurred (InvalidParameterCombination) when calling the StopDBInstance operation: aurora-mysql DB instances are not eligible for stopping and starting.
Cannot stop instance portal-rds-1.

 

아래는 변경된 코드이며 클러스터를 중단한다. 

성공시 아래 로그가 발생한다.

 

  • Log
Stopping cluster: my-cluster-name
  • code in Python
import boto3
rds = boto3.client('rds')

def lambda_handler(event, context):

    #Stop DB clusters
    dbi = rds.describe_db_instances()
    print (dbi)
    dbs = rds.describe_db_clusters()
    print (dbs)
    
    for db in dbs['DBClusters']:
        #Check if DB instance is not already stopped
        if (db['Status'] == 'available'):
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBClusterArn'])['TagList']
                for tags in GetTags:
                #if tag "autostop=yes" is set for cluster, stop it
                    if(tags['Key'] == 'autostop' and tags['Value'] == 'yes'):
                        result = rds.stop_db_cluster(DBClusterIdentifier=db['DBClusterIdentifier'])
                        print ("Stopping cluster: {0}.".format(db['DBClusterIdentifier']))
            except Exception as e:
                print ("Cannot stop rds {0}.".format(db['DBClusterIdentifier']))
                print(e)
                
if __name__ == "__main__":
    lambda_handler(None, None)

+ Recent posts