Docker private registry 간편 설정 KOPS

이 전 글에서 kubernetes 에 docker private registry 를 사용하는 방법 에 대해 기술 했습니다.

하지만 막상 사용하다보면 매번 imagePullSecrets 을 입력해줘야하는 불편함이 있습니다.

해서 각 노드마다 docker.json 을 배포해주면 되지 않을까 싶어서 찾아보다보니 kops 에서 자체적으로 지원합니다.

kops/security.md at master · kubernetes/kops · GitHub

위 링크를 가면 아래와 같은 방법이 나옵니다만…

kops create secret --name <clustername> dockerconfig -f ~/.docker/config.json
kops rolling-update cluster --name <clustername> --yes

제 현재 상황에서는 rolling-update 를 실행해도 변화된것이 없다고 적용이 되지 않더군요.

현재 버전

KOPS Version: 1.10.0 (git-8b52ea6d1)
kubernetesVersion: 1.10.6

방법은 간단합니다. 강제로 rolling-update를 수행하면 됩니다.

kops rolling-update cluster --name <clustername> --yes --force

이제 손쉽게 docker private registry를 사용할 수 있습니다.

Kubernetes + private docker registry

kubernetes 설정이 완료 되었으면, 이제 실제로 kubernetes 를 사용하기 위한 docker registry 연동 설정을 해보겠습니다.

보통 회사에서 사용할 때는 자체 private docker registry 를 사용하고 있을 겁니다.

이 registry 를 kubectl 을 이용해서 연동해봅시다.

Set up Docker Registry

Pull an Image from a Private Registry – Kubernetes
위 글을 참고 하여 연동을 합니다.

등록

Usage:

kubectl create secret docker-registry NAME –docker-username=user –docker-password=password –docker-email=email [–docker-server=string] [–from-literal=key1=value1] [–dry-run] [options]

kubectl create secret docker-registry regcred --docker-server=https://example.com --docker-username=aws --docker-password="abcd1234" --docker-email="aws@example.com"

Docker-registry secret 이름을 여기서는 regcred로 생성해서 만들었습니다.

확인

kubectl get secret regcred --output=yaml

Output:

apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodH3FovL2RyZWcuYcyI6eyJodH3FovMiLCJwYXNzd29yZCI6ImdyYWNlbm90ZTEyIUAiLC3D2KWFpbCI6ImF3c0BncmFjZW5vdGUuY29tIiwiYXV0aCI6IllYZHpPbWR5WVdObGJcyI6eyJodH3FovJ9fX0=
kind: Secret
metadata:
  creationTimestamp: 2018-07-11T06:15:56Z
  name: regcred
  namespace: default
  resourceVersion: "6036405"
  selfLink: /api/v1/namespaces/default/secrets/regcred
  uid: df5d178b-84d1-11e8-b74a-0e9d5423172c
type: kubernetes.io/dockerconfigjson

출력 결과에서 .dockerconfigjosn이라는 내용은 실제 docker registry 접속정보를 나타냅니다. 아래 명령을 통해 정상적으로 접속정보가 들어갔는지 확인 해 볼 수 있습니다.

kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d

맥북일 경우는 -d 옵션을 대문자  -D 로 변경합니다.  

kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -D

Output:

{"auths":{"https://example.com":{"username":"aws","password":"abcd1234","email":"aws@example.com","auth":"YxDAOmdyKZNlbm30ZTEyIUA="}}}

TEST

이제 설정은 완료됐습니다.
실제 pod 를 배포해서 정상적으로 동작하는지 TEST 해 봅시다.

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container-nginx
    image: example.be/devops/nginx-custom:0.1.0
  imagePullSecrets:
  - name: regcred

위의 내용으로 my-private-reg-pod.yml 파일을 생성합니다.

kubectl create -f my-private-reg-pod.yml

위 명령 실행후 정상적으로 pod 생성이 되는지 확인합니다.

kubectl get po private-reg

Output:

 ✘ ktg@dev-vm-of00-016  ~/projects/k8s kubectl get po private-reg
NAME                            READY     STATUS    RESTARTS   AGE
private-reg                     1/1       Running   0          1m

STATUS 가 Running 이면 정상동작하는 것을 알수 있습니다.

curl로 nginx 작동 여부를 확인하고 싶다면,

kubectl exec -it private-reg (bash or sh)
curl localhost

위 명령을 실행 하면 됩니다.

kubernetes + Kops + ExternalDNS 정리 – 2

kubernetes + kops + externalDNS 정리 두번째

첫번째 내용은 여기서 확인 가능합니다.

여기서는 Route53 연동을 위한 ExternalDNS를 알아봅니다.

kubernetes + kops with ExternalDNS


이제 service expose 가 필요한 Services 들을 위해 Route53 연동을 시작해봅시다.

Install ExternalDNS

external-dns/aws.md at master · kubernetes-incubator/external-dns · GitHub

위 링크에 가면 ExternalDNS on AWS 에 대한 설명이 나옵니다.
여기서 중요하게 집고 넘어가야할 부분이 IAM 설정입니다.
저는 처음에 kops IAM 설정에 위의 설정들이 다 들어가 있기 때문에 괜찮을 거라고 생각하고 넘어갔다가 상당히 고생했습니다.

위 링크에서 설명하고 있는 IAM은 k8s의 node role 에 대한 설정입니다.
kops 로 클러스터를 구성하면, master node와 nodes 들의 role들이 별도로 관리가. 됩니다.

아래에서 IAM permission for nodes 를 설정 하겠습니다.

Edit Cluster

kops 를 통해 cluster 에 ExternalDNS 사용을 위한 설정을 추가해줍니다.

kops edit cluster $NAME

위 명령 실행 시 vim 화면이 뜹니다.
내용을 살펴보면 cluster 설정에 대한 yaml 파일 입니다.

Route53 설정을 위해 아래 내용을 하단에 추가해줍니다.

  additionalPolicies:
    node: |
      [
        {
          "Effect": "Allow",
          "Action": [
            "route53:ChangeResourceRecordSets"
          ],
          "Resource": [
            "arn:aws:route53:::hostedzone/*"
          ]
        },
        {
          "Effect": "Allow",
          "Action": [
            "route53:ListHostedZones",
            "route53:ListResourceRecordSets"
          ],
          "Resource": [
            "*"
          ]
        }
      ]

위 내용은 node role 에 추가로 IAM policy 설정을 해준다는 의미입니다.
node 이외에도 master, bastion이 있습니다.
관련링크 입니다.
kops/iam_roles.md at master · kubernetes/kops · GitHub

이제 cluster 에 변경사항을 적용해줍니다.

kops update cluster --yes $NAME

이제 AWS console 에서 IAM 의 Role 에서 추가된 Policy 를 확인 하실 수 있습니다.

The additional Policy image

ExternalDNS on AWS


이제 어플을 배포 해보겠습니다.
배포하기전에 앞에 해야할 일이 ExternalDNS 를 kubernetes 에 생성하는 것입니다.

ExternalDNS 생성

external-dns/aws.md at master · kubernetes-incubator/external-dns · GitHub
위 링크에 있는 external-dns example 을 사용하겠습니다.
RBAC enabled 된 example 입니다.

external-dns.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["extensions"] 
  resources: ["ingresses"] 
  verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: registry.opensource.zalan.do/teapot/external-dns:v0.5.0
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=k8s.example.com. # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
        - --provider=aws
        - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)

저장 후에 생성합니다.

kubectl create -f external-dns.yaml

Output:

serviceaccount "external-dns" created
clusterrole.rbac.authorization.k8s.io "external-dns" created
clusterrolebinding.rbac.authorization.k8s.io "external-dns-viewer" created
deployment.extensions "external-dns" create

Pod가 잘 실행 되었는지 확인

kubectl get po

Output

9to5-macbook:~/projects/k8s ktg$ kubectl get po
NAME                            READY     STATUS    RESTARTS   AGE
curl-545bbf5f9c-rlpwb           1/1       Running   1          6d
external-dns-75d57587fc-dkk8s   1/1       Running   0          43s
hello-go-6db785ccbd-94vdh       1/1       Running   0          6d
nginx-proxy-7b775767b6-fngcz    1/1       Running   0          6d

ExternalDNS Pod 의 로그 확인

kubectl logs -f $(kubectl get po -l app=external-dns -o name)

Output:

9to5-macbook:~/projects/k8s ktg$ kubectl logs -f $(kubectl get po -l app=external-dns -o name)
time="2018-05-17T09:18:45Z" level=info msg="config: {Master: KubeConfig: Sources:[service ingress] Namespace: AnnotationFilter: FQDNTemplate: CombineFQDNAndAnnotation:false Compatibilit$
: PublishInternal:false Provider:aws GoogleProject: DomainFilter:[k8stest.example.com.] ZoneIDFilter:[] AWSZoneType:public AWSAssumeRole: AzureConfigFile:/etc/kubernetes/azure.json AzureRe
sourceGroup: CloudflareProxied:false InfobloxGridHost: InfobloxWapiPort:443 InfobloxWapiUsername:admin InfobloxWapiPassword: InfobloxWapiVersion:2.3.1 InfobloxSSLVerify:true DynCustomerN
ame: DynUsername: DynPassword: DynMinTTLSeconds:0 InMemoryZones:[] PDNSServer:http://localhost:8081 PDNSAPIKey: Policy:sync Registry:txt TXTOwnerID:default TXTPrefix: Interval:1m0s Once:
false DryRun:false LogFormat:text MetricsAddress::7979 LogLevel:info}"
time="2018-05-17T09:18:45Z" level=info msg="Connected to cluster at https://100.64.0.1:443"
time="2018-05-17T09:18:46Z" level=info msg="All records are already up to date"
...

정상 동작을 확인했습니다.

이제 실제 우리가 서비스에 사용할 app 을 배포해봅시다.
여기서 예제는 nginx 입니다.

NGINX 배포

nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: nginx.k8s.example.com.
spec:
  type: LoadBalancer
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
          name: http

Deploy and Service 생성

9to5-macbook:~/projects/k8s ktg$ kubectl create -f example/nginx.yaml
service "nginx" created
deployment.extensions "nginx" created

Service nginx 정보 확인

9to5-macbook:~/projects/k8s ktg$ kubectl describe svc nginx
Name:                     nginx
Namespace:                default
Labels:                   <none>
Annotations:              external-dns.alpha.kubernetes.io/hostname=nginx.k8s.example.com.
Selector:                 app=nginx
Type:                     LoadBalancer
IP:                       100.68.183.89
LoadBalancer Ingress:     af2addc7959b811e888e41234567890-1234567890.us-east-1.elb.amazonaws.com
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31243/TCP
Endpoints:                100.96.2.16:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  EnsuringLoadBalancer  1m    service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   1m    service-controller  Ensured load balancer

Load Balancer url test

curl af2addc7959b811e888e41234567890-1234567890.us-east-1.elb.amazonaws.com

ExternalDNS Pod 의 로그 다시 확인

kubectl logs -f $(kubectl get po -l app=external-dns -o name)

Output:

...
time="2018-05-17T09:59:49Z" level=info msg="Desired change: CREATE nginx.k8s.example.com A"
time="2018-05-17T09:59:49Z" level=info msg="Desired change: CREATE nginx.k8s.example.com TXT"
time="2018-05-17T09:59:49Z" level=info msg="Record in zone k8s.example.com. were successfully updated"
...

로그에서 위의 메시지를 찾으면 정상적으로 Route53 에 A record가 생성 되었습니다.

잠시 후에 해당 url 에 request 를 보내봅니다.

curl nginx.k8s.example.com

Load balancer url 에 request 를 보냈을 때와 같은 결과가 나온다면 정상적으로 kubernetes cluster 설정이 완료된 것입니다.

kubernetes + Kops + ExternalDNS 정리 – 1

kubernetes + Kops + ExternalDNS 정리


AWS 서비스에서 kops를 활용해서 kubernetes cluster를 구성해보고,
AWS의 DNS 서비스인 Route53에 ExternalDNS라는 Plugin을 통해 연동해보겠습니다.

이 글은 kubernetes study를 하며 알게된 부분을 정리하는데 목적이 있습니다.

Prerequisite

  • kops 1.9.0
  • kubectl client v1.10.1, server v1.9.3
  • externalDNS **v0.5.0
  • aws-cli/1.11.69 Python/2.7.10 Darwin/17.5.0 botocore/1.5.32
  • jq v1.5

install

아래 링크대로 따라서 Kops 설치
Following this ref

Get started


이제 쿠베 설정을 해보겠습니다.

kops IAM settings


kops/aws.md at master · kubernetes/kops · GitHub
위의 링크를 참고해서 IAM 에서 해당 권한을 가진 user 생성

The kops user will require the following IAM permissions to function properly:

AmazonEC2FullAccess
AmazonRoute53FullAccess
AmazonS3FullAccess
IAMFullAccess
AmazonVPCFullAccess

User created save on local machine

로컬 aws-cli 에서 사용할 access key 와 secret key 저장

vi ~/.aws/credentials

~/.aws/credentials

[DevelopRole]
aws_access_key_id = AKIAAAAAA4FEOBBB65BA
aws_secret_access_key = aNVAAAAAACavjag5HvO7BBBbbebG/ewDefWdFicq

Domain settings


먼저 도매인이 없다면 구매를 해야합니다.
buy your own domain
구매후 약간의 시간이 필요합니다.

도매인(example.com)이 있다고 가정하고 진행합니다.
kops/aws.md at master · kubernetes/kops · GitHub

parent domain ID 확인

aws --profile DevelopRole route53 list-hosted-zones | jq '.HostedZones[] | select(.Name=="example.com.") | .Id'

Output

"/hostedzone/ZKASHKH31HAHA"

create subdomain

ID=$(uuidgen) && aws --profile DevelopRole route53 create-hosted-zone --name k8s.example.com --caller-reference $ID | \
    jq .DelegationSet.NameServers

Output

[
  "ns-1234.awsdns-17.org",
  "ns-400.awsdns-60.com",
  "ns-800.awsdns-38.net",
  "ns-1800.awsdns-46.co.uk"
]

위의 output 내용을 아래처럼 subdomain.json 파일에 저장합니다.

subdomain.json

{
  "Comment": "Create a subdomain NS record in the parent domain",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "k8s.example.com",
        "Type": "NS",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "ns-1234.awsdns-17.org"
          },
          {
            "Value": "ns-400.awsdns-60.com"
          },
          {
            "Value": "ns-800.awsdns-38.net"
          },
          {
            "Value": "ns-1800.awsdns-46.co.uk"
          }
        ]
      }
    }
  ]
}

Parent domain 에 subdomain 정보를 저장합니다.

aws --profile DevelopRole route53 change-resource-record-sets \
 --hosted-zone-id "/hostedzone/ZKASHKH31HAHA" \
 --change-batch file://subdomain.json

Output

{
    "ChangeInfo": {
        "Status": "PENDING",
        "Comment": "Create a subdomain. NS record in the parent domain",
        "SubmittedAt": "2018-05-09T08:12:45.256Z",
        "Id": "/change/C3GYMM3KUW8HAC"
    }
}

Testing your DNS setup

dig ns k8s.example.com

Output

; <<>> DiG 9.10.6 <<>> ns k8s.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 643
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;k8s.example.com.           IN  NS

;; ANSWER SECTION:
k8s.example.com.        300 IN  NS  ns-480.awsdns-60.com.
k8s.example.com.        300 IN  NS  ns-820.awsdns-38.net.
k8s.example.com.        300 IN  NS  ns-1909.awsdns-46.co.uk.
k8s.example.com.        300 IN  NS  ns-1162.awsdns-17.org.

;; Query time: 880 msec
;; SERVER: 10.3.21.236#53(10.3.21.236)
;; WHEN: Wed May 09 17:14:59 KST 2018
;; MSG SIZE  rcvd: 182

kops S3 settings


kops에서는 S3를 사용합니다.
S3에 저장된 데이터를 이용해서 다중 사용자가 같은 kubernetes cluster를 컨트롤할 수 있게 합니다.

Create s3 bucket for saving cluster state

clusters.k8s.example.com S3 bucket 을 생성합니다.

aws --profile DevelopRole s3 mb s3://clusters.k8s.example.com

kops/aws.md at master · kubernetes/kops · GitHub

아래 이유를 들어 kops팀에서는 versionning 설정을 추천하고 있습니다.
설정 해줍시다.

Note: We STRONGLY recommend versioning your S3 bucket in case you ever need to revert or recover a previous state store.

Versioning

aws --profile DevelopRole s3api put-bucket-versioning --bucket clusters.k8s.example.com --versioning-configuration Status=Enabled

앞으로 있을 kops 사용을 위해 아래 3가지를 environment variables 에 등록 해 줍니다.

export KOPS_STATE_STORE=s3://clusters.k8s.example.com
export AWS_PROFILE=DevelopRole
export NAME=useast1.k8s.example.com

kubernetes cluster settings by kops


이제 드디어 쿠베 클러스터에 대한 설정을 시작합니다.
위의 내용은 쿠베 클러스터 설정을 kops로 하기위한 준비과정으로 보시면 됩니다.

Create cluster configuration.

어떤 az 를 사용할 지 ,를 사용해서 선택합니다.

kops create cluster --zones="us-east-1a,us-east-1c" useast1.k8s.example.com
kops create cluster \
 --cloud=aws \
 --zones="us-east-1a" \
 --name $NAME \
 --vpc vpc-d71411b2 \
 --ssh-public-key="~/.ssh/id_rsa.pub"

Note: 아직 cluster 가 생성된 것은 아닙니다. 실제 적용을 위해서는 kops update cluster —yes 명령이 추가로 필요합니다.

Master / node check

cluster 는 마스터 노드와 마스터노드가 관리하는 여러 노드들로 구성 됩니다.
현재 구성을 아래 명령을 통해 확인 합니다.

kops get ig --name $NAME

Output

NAME            ROLE    MACHINETYPE MIN MAX ZONES
master-us-east-1a   Master  t2.small    1   1   us-east-1a
nodes           Node    t2.small    2   2   us-east-1a

노드 타입을 본인이 원하는 사이즈로 변경하고 싶을 경우, 아래 명령을 통해 가능합니다.

edit master spec

kops edit ig master-us-east-1a --name $NAME
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: 2018-05-10T04:40:40Z
  labels:
    kops.k8s.io/cluster: useast1.k8s.example.com
  name: master-us-east-1a
spec:
  cloudLabels:
    Email: ktk0011+dev@gmail.com
    Owner: 9to5
    Team: devops
  image: kope.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-02-08
  machineType: m4.large
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: master-us-east-1a
  role: Master
  subnets:
  - us-east-1a

이때 spec 하단에 aws instance가 생성될 때 aws의 tagcloudLabels 을 통해 미리 달아줄 수 있습니다.

cloudLabels:
    Email: ktk0011+dev@gmail.com
    Owner: 9to5
    Team: devops

여기서는 instance typecloudLabels 만을 변경했습니다.

edit nodes spec

노드의 설정 또한 변경해줍니다.

kops edit ig nodes --name $NAME
apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: 2018-05-10T04:40:41Z
  labels:
    kops.k8s.io/cluster: useast1.k8s.example.com
  name: nodes
spec:
  cloudLabels:
    Email: ktk0011+dev@gmail.com
    Owner: 9to5
    Team: devops
  image: kope.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-02-08
  machineType: c4.large
  maxSize: 2
  minSize: 2
  nodeLabels:
    kops.k8s.io/instancegroup: nodes
  role: Node
  subnets:
  - us-east-1a

원하시면 cluster 구성시에 사용할 instance size 를 늘려주시면 됩니다.

Apply cluster

이제 클러스터를 실제 aws instance 에 적용해 봅시다.
kops는 dry-run을 지원하기 때문에 —yes 없이 실행하면 변경내역을 미리 확인 해볼 수 있습니다.

kops update cluster --yes $NAME

이제 kubernetes cluster 구성이 완료 되었습니다.

check cluster

Nodes 들이 잘 동작하는지 확인 해봅시다.

kubectl get nodes

Output

9to5-macbook:~/projects/k8s ktg$ kubectl get nodes
NAME                            STATUS    ROLES     AGE       VERSION
ip-10-110-39-39.ec2.internal    Ready     node      6d        v1.9.3
ip-10-110-47-235.ec2.internal   Ready     master    6d        v1.9.3
ip-10-110-63-48.ec2.internal    Ready     node      6d        v1.9.3

StatusReady 입니다. 이제 kubernetes 를 사용할 수 있습니다!!… 만!

실제 서비스를 쿠베에서 사용하려면, route53 연동은 필수 입니다. 외부에서 kubernetes 로 접근하려면, 당연히 dns 가 필요하기 때문입니다. ip는 계속 변할 수 있기 때문에…

Route53연동은 다음 글에서 계속 하겠습니다.

Kubernetes on AWS + kops

Kubernetes on AWS + kops

Prerequisite

  • kops 1.9.0
  • kubectl client v1.10.1, server v1.9.3

설치

아래 링크대로 따라서 설치
Following this ref

그리고 어김없이 찾아오는 에러…

Error

kops 로 클러스터 구성(after executing, kops update cluster —yes $NAME) 후에 아래와 같은 output 을 볼수 있습니다.

...

Suggestions:
 * validate cluster: kops validate cluster
 * list nodes: kubectl get nodes --show-labels
 * ssh to the master: ssh -i ~/.ssh/id_rsa admin@api.useast1.k8s.example.com
 * the admin user is specific to Debian. If not using Debian please use the appropriate user based on your OS.
 * read about installing addons at: https://github.com/kubernetes/kops/blob/master/docs/addons.md.

아래 명령을 실행합니다.

kops validate cluster

Output:

tkwon-macbook:~/projects/k8s ktg$ kops validate cluster
Using cluster from kubectl context: useast1.k8s.example.com

Validating cluster useast1.k8s.example.com

INSTANCE GROUPS
NAME            ROLE    MACHINETYPE MIN MAX SUBNETS
master-us-east-1a   Master  m5.large    1   1   us-east-1a
nodes           Node    c5.large    2   2   us-east-1a

NODE STATUS
NAME    ROLE    READY

VALIDATION ERRORS
KIND    NAME        MESSAGE
dns apiserver   Validation Failed

The dns-controller Kubernetes deployment has not updated the Kubernetes cluster's API DNS entry to the correct IP address.  The API DNS IP address is the placeholder address that kops creates: 203.0.113.123.  Please wait about 5-10 minutes for a master to start, dns-controller to launch, and DNS to propagate.  The protokube container and dns-controller deployment logs may contain more diagnostic information.  Etcd and the API DNS entries must be updated for a kops Kubernetes cluster to start.

Validation Failed

뭔지 모르겠지만 실패했습니다.
ssh로 master node 에 접속 시도 해봅니다.

ssh -i ~/.ssh/id_rsa admin@api.useast1.k8s.example.com

ssh 접속이 되지 않았습니다. ..

route53에서 확인해보니 도매인의 ip가 master node ip로 변경되어 있지 않았습니다.

Ec2 dashboard 를 확인하니 정상적으로 instance가 실행중입니다.

ip로 ssh 접속 시도합니다.

ssh -i ~/.ssh/id_rsa admin@1.1.1.1

정상적으로 접속됩니다.

sudo docker ps

Output:

protokube                                          1.9.0

protokube 라는 이미지가 실행중입니다.
docker log 를 확인해보니 아래와 같은 에러로그가 반복되고 있습니다.

...
Mar 30 22:30:38 ip-172-31-1-13 docker[1546]: I0330 22:30:38.659365    1576 aws_volume.go:318] nvme path not found "/rootfs/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol0f1a04a36c6baaaae"
Mar 30 22:30:38 ip-172-31-1-13 docker[1546]: I0330 22:30:38.659373    1576 volume_mounter.go:107] Waiting for volume "vol-0f1a04a36c6baaaae" to be attached
Mar 30 22:30:39 ip-172-31-1-13 docker[1546]: I0330 22:30:39.659499    1576 aws_volume.go:318] nvme path not found "/rootfs/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol0f1a04a36c6baaaae"
Mar 30 22:30:39 ip-172-31-1-13 docker[1546]: I0330 22:30:39.659519    1576 volume_mounter.go:107] Waiting for volume "vol-0f1a04a36c6baaaae" to be attached
Mar 30 22:30:40 ip-172-31-1-13 docker[1546]: I0330 22:30:40.659641    1576 aws_volume.go:318] nvme path not found "/rootfs/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol0f1a04a36c6baaaae"
Mar 30 22:30:40 ip-172-31-1-13 docker[1546]: I0330 22:30:40.659660    1576 volume_mounter.go:107] Waiting for volume "vol-0f1a04a36c6baaaae" to be attached
...

검색해보니,
Cluster hung up starting, waiting for etcd volumes to attach · Issue #4844 · kubernetes/kops · GitHub

위의 링크에 원인이 나와있었습니다.
thumb up 한번 눌러드리고 수정합니다.

$ kops edit ig master-us-east-1a
$ kops edit ig nodes

위 명령을 실행해서 instance type m5, c5 에서 m4, c4로 바꿉니다.

kops rolling-update cluster --cloudonly --yes

실행하고… 기다립니다.

kops validate cluster

Output:

tkwon-macbook:~/projects/k8s ktg$ kops validate cluster
Using cluster from kubectl context: useast1.k8s.example.com

Validating cluster useast1.k8s.example.com

INSTANCE GROUPS
NAME            ROLE    MACHINETYPE MIN MAX SUBNETS
master-us-east-1a   Master  m4.large    1   1   us-east-1a
nodes           Node    c4.large    2   2   us-east-1a

NODE STATUS
NAME                ROLE    READY
ip-10-110-42-179.ec2.internal   node    True
ip-10-110-45-25.ec2.internal    master  True
ip-10-110-47-243.ec2.internal   node    True

Your cluster useast1.k8s.example.com is ready

이제 kubernetes cluster 를 사용할 수 있습니다!

AWS t2 tier 이용하기 – swap memory

AWS t2 tier 이용하기 – swap memory

문제점

회사에서 Aws t2.small 티어를 이용하던 중에 Alertmanager 로 부터 아래의 alert message 를 받게 되었습니다.

메시지를 확인해보니 제가 회사에서 관리하는 docker 모듈들을 간단히 web에 확인해보고자 설치한 Portainer | Simple management UI for Docker 인스턴스가 Memory swap 용량을 절반 이상을 사용했다고 합니다.

Instance 에 접속해서 memory 를 확인합니다.

$ free -mh

Swap memory 가 1M? 2M? 정도 밖게 되지 않습니다.

그래서 아무도 사용하지 않는(..) portainer 인스턴스에서 괴상하게 얼럿이 날라왔던 것입니다.

해결책

해결을 위해 관련 정보를 찾아봅니다.

Adding swap space to an EC2 Amazon Linux instance – PTS: Technical Consulting

위의 포스팅 대로 따라하면 손쉽게 스왑메모리를 확보할 수 있습니다…만,

전 간단하게 불필요한걸로 보이는 명령은 빼고 아래 명령만 실행했습니다.

sudo swapoff -a
sudo dd if=/dev/zero of=/var/swapfile bs=1M count=1024   
sudo mkswap /var/swapfile
sudo swapon /var/swapfile
sudo swapon -s

free -mh

간단히 스왑을 끄고, 1기가 스왑 파일 할당후에 스왑 적용 했습니다.

제가 사용한 인스턴스는 t2.small 로 1G의 스왑메모리가 적당하다고 판단해서 만들었습니다.

용량은 각자 지정하면 될 듯 합니다.

결론

  • aws t2 tier 의 인스턴스를 사용할 경우 OOM이 나은 선택일 경우는 그냥 쿨하게 더 높은 인스턴스를 사용하자.
  • 느려져도 관계없이 잘 돌아가기만 해도 되는 서비스라면, t2 사용시 swap 메모리를 항상 조정해주자.

[AWS] Amazon web service 의 서비스 간단 정리

AWS 서비스 정리

AWS를 공부해야겠다고 마음먹고 AWS를 막상 시작하려고 하면,
그 방대한 사이즈에 지래 겁을 먹게 됩니다.
또한 AWS의 어떤 특정 기능에 대해 찾아보려고 하면 또다른 AWS서비스들이 연계되어서 다시 리서치를 해야하는 번거로움에 빠지게 됩니다.

이에 저의 고생을 경험삼아 다른분들의 고생을 미리 방지하고자 사람들을 위해 AWS 서비스를 간단하게 정리했습니다.

EC2(Amazon Elastic Compute Cloud)

VM기반의 컴퓨팅 자원을 제공하는 서비스
일반적인 클라우드 서버 인스턴스를 의미

Instance Family Current Generation Instance Types
General purpose t2.nano, t2.micro, t2.small, t2.medium, t2.large, t2.xlarge, t2.2xlarge, m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge, m4.16xlarge, m3.medium, m3.large, m3.xlarge, m3.2xlarge
Compute optimized c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, c3.large, c3.xlarge, c3.2xlarge, c3.4xlarge, c3.8xlarge
Memory optimized r3.large, r3.xlarge, r3.2xlarge, r3.4xlarge, r3.8xlarge, r4.large, r4.xlarge, r4.2xlarge, r4.4xlarge, r4.8xlarge, r4.16xlarge, x1.16xlarge, x1.32xlarge
Storage optimized d2.xlarge, d2.2xlarge, d2.4xlarge, d2.8xlarge, i2.xlarge, i2.2xlarge, i2.4xlarge, i2.8xlarge, i3.large, i3.xlarge, i3.2xlarge, i3.4xlarge, i3.8xlarge, i3.16xlarge
Accelerated computing p2.xlarge, p2.8xlarge, p2.16xlarge, g2.2xlarge, g2.8xlarge
  1. T2는 웹서버, 데이터 베이스에 사용하기 좋음, 순간 확장용으로 적합
  2. M3는 SSD 스토리지 사용
  3. C4는 CPU를 많이 쓰는 서비스에 적합 -> ssd도 필요하면 C3
  4. X1, R3은 메모리가 많이 필요한 서비스에 적합(빅데이터 치리 엔진, Apache Spark, Presto)
  5. P2, G2는 GPU 계산에 특화 (머신러닝)
  6. I3는 스토리지에 최적화 (높은 I/O가 필요한 작업)

EBS(Elastic Block Store)

EC2 인스턴스에 사용할 영구 블록 스토리지 볼륨을 제공
Amazon EBS 볼륨은 워크로드 실행에 필요한 지연 시간이 짧고 일관된 성능을 제공 -> S3와의 큰 차이점

그러나 S3에 비해 비쌈

EIP(Elastic IP)

EC2인스턴스를 생성하고 주는 IP는 고정IP가 아닌 유동IP
인스턴스를 재시작하면 IP가 변경됨
고정아이피 서비스 -> EIP

ELB(Elastic Load Balancing)

EC2를 대상으로한 요청을 여러대의 EC2 인스턴스로 자동으로 분배해주는 기능
이전엔 L4/L7 로드 밸런서를 이용하던 기능을 간단한 WEB UI로 손쉽게 이용가능

로드 밸런서는 EC2의 작동 상태를 확인하여 정상적으로 작동하고 있는 인스턴스만을 대상으로 요청을 분배함

Sticky Session을 이용하면 로드밸런싱을 해줄 때 사용자의 쿠키 세션을 이용해여 요청 분배작업을 수행, 초기 접속 인스턴스로 연결 시켜줌

Key Pairs

AWS ssh접속public/private 키를 이용하여 접속
각각의 key pair에는 이름이 필요하고, 이름은 publickey와 연결됨

Security Group

EC2에서 일종의 방화벽 처럼 사용됨
inbound/outbound traffic에 대해 port별로 접근 제어할 수 있는 기능 제공
호스팅 환경에서 DMZ와 같은 개념 구현 가능

S3 (Simple Storage Service)

웹 인터페이스를 통해 데이터를 저장 및 검색할 수 있는 스토리지
RRS(Reduced Redundancy Storage) 옵션으로 데이터 손실 위험도를 더 올리고 가격을 저렴하게 사용가능

Bucket

데이터를 저장하기 위한 Amazon S3의 기본 컨테이너
버킷에 데이터를 무한정으로 저장 가능

Snapshot

EBS 볼륨 전체의 내용 중 특정 시점을 파일로 저장한 형태 (EBS 볼륨 백업)

VPC(Virtual Private Cloud)

AWS에서 가상사설망을 만들어줄수 있게 해주는 서비스
이 서비스 전에는 EIP이외에는 정적 서비스를 사용할 수 없었음(ex> 10.x.x.x같은 사설 ip 사용하지 못했으나, VPC를 통해 가능해짐)

Lambda

서버없이 특정 이벤트 발생시 코드 실행을 시켜주고, 이에 대한 비용만을 지불하는 AWS의 서비스
런타임으로 Java, nodejs, python, C# 사용가능

Blue Print라는 코드 템플릿을 선택해서 사용가능하다

Route 53

AWS의 Domain Name Service 이다.
ELB(로드 밸런서)를 사용할 때 함께 사용하는 서비스

라우팅 정책

  1. 단순 라우팅
    하나의 인스턴스 사용
  2. 가중치 기반 라우팅
    다수의 리소스를 하나의 DNS와 연동 가능하나, 각 리소스에 가중치 부여 가능

    리소스 3개 -> 가중치 1,1,3 부여했을 경우
    DNS요청시 1로 설정된 리소스는 5번중 한번, 3으로 설정된 리소스는 5번중 3번 반환

  3. 지연 시간 라우팅
    지연시간이 가장 낮은 인스턴스 선택

  4. 지리적 라우팅
    사용자의 지역에 따라 인스턴스 선택 -> Localization 가능

ElastiCache

클라우드에서 In Memory Data Store로 사용 하거나, 캐시를 손쉽게 배포, 운영, 확장할 수 있게 해주는 웹서비스

  1. Redis
    RedisElastiCache는 확장 가능(최대 15개의 샤드 클러스터 지원 3.55TiB)
  2. Memcached
    ElastiCacheMemcached와 프로토콜 호환. 기존 환경에서 사용하는 도구를 손쉽게 사용 가능

CloudFront

AWS에서 제공하는 CDN서비스
이미지, 오디오, 비디오 및 일반 웹 페이지 등을 최종 사용자에게 빠르게 제공
에지 로케이션(Edge Location)이라는 일종의 캐시서버를 이용하여 지연시간 단축

IAM(Identity and Access Management)

AWS 계정의 암호나 액세스 키 공유없이 다른 계정에 권한 부여 가능

  1. 리소스에 따른 계정 권한
  2. 읽기 쓰기 권한 등.. -> 차등 권한 부여 가능

사용자

AWS의 서비스 계정으로 간주하면 됨

윈도우즈를 사용할 때 여러 계정을 만들 수 있는 것과 같은 이치

ARN(Amazon Resource Name)

아래 형태로 사용

arn:aws:iam::account-ID-without-hyphens:user/Bob

그룹

IAM사용자들의 집합체
but 리눅스의 group개념과는 다른 그냥 여러 사용자들에게 한번에 정책을 연결하는 수단일 뿐

역할

사용자와 유사
_but 역할은 한 사람과만 연관되지 않고 그 **역할이 필요한 사람이면 누구든지 맡을 수 있도록 고안**_

CodeCommit

프라이빗 Git 리포지토리를 손쉽게 운영할 수 있는 서비스
가격이 싸다

SNS(Simple Notification Service)

푸시 알림 서비스로서, 개별 메시지를 전송하거나 대규모의 수신자에게 메시지를 전송 가능
Baidu Cloud Push를 통해 Android, Apple, Google, Fire OS, Windows 디바이스에도 알림 전송 가능
Amazon Simple Queue Service(SQS), AWS Lambda 함수 또는 모든 HTTP 엔드포인트에도 메시지를 전송 가능

토픽(Topic)

여러 개의 엔드포인트를 그룹으로 만든 것. 토픽을 구독한 모든 엔드포인트로 알림 전송

SQS(Simple Queue Service)

메시지를 저장하는 대기열에 대한 액세스를 제공하는 웹 서비스

메시지 큐

대기열 유형

  1. 표준 대기열
    기본 대기열, 메시지가 1개 이상 전달될 수 있으며 순서 또한 바뀔 수 있음
    무제한의 초당 트랜잭션 수 제공
  2. FIFO 대기열
    순서 및 메시지 단일 전달 보장
    초당 트랜잭션 수가 300개 제한

CloudWatch

AWS 클라우드 리소스와 AWS에서 실행되는 애플리케이션을 위한 모니터링 서비스
자동으로 EC2 인스턴스를 모니터링
1. Auto Scaling Group
2. Elastic Load Balancer
3. Route 53

메트릭(Metric)

AWS 시스템의 퍼포먼스에 관한 데이터들을 뜻함

기본적으로 제공하는 CloudWatch의 모니터링 기능은 이 메트릭을 이용해서 보여진다(EC2, ELB등의 기본 서비스 관련 정보등..)
사용자가 커스텀 메트릭 생성가능

상태는 3가지

  1. OK
    정의된 임계치 안, 현재 정상
  2. Alarm
    정의된 임계치 상회, 비정상
  3. Insufficient
    데이터 불충분으로 상태 판독 불가

Auto Scaling

Auto Scaling이란?

EC2 인스턴스를 자동으로 생성하고 삭제해주는 서비스

Launch Configuration

Auto Scaling을 할 때 사용하는 설정값

어떤 이미지(AMI)를 어떤 인스턴스 타입(EC2)으로 스토리지(EBS) 및 보안설정(SG)과 함께 사용할 것인가를 선택

ex> Linux AMI 이미지를 t2.micro로 EBS 20G와 함께 port 80번만을 열어서 실행한다.

AutoScaling Groups

위의 설정값을 사용해서 실제 Auto Scaling을 수행하기 위한 Grouping

어떤 설정값으로, 어떤 네트워크에, 어떤 정책(인스턴스를 추가하고 제거하는 방법 등의 정책)을 이용해서 오토 스케일링을 할 것 인가에 대한 설정

ex> ASG을 통해서 생성된 EC2 인스턴스들의 CPU 점유율이 평균 80%가 5분동안 넘을 때 EC2 인스턴스를 현재의 2배씩 증가 시킨다

OpsWorks

서버 구성을 자동화 플랫폼 Chef를 사용해서 하는 관리 서비스
어플리케이션과 서버 관리를 용의하게 해줌

  1. OpsWorks Stacks
  2. AWS OpsWorks for Chef Automate

OpsWorks Stacks

OpsWorks 개념도

위의 개념도를 참고.

Stack > Layer > Instance > App

Stack

스택은 OpsWorks에서 최상위 단위
스택안에 여러 개의 레이어가 포함가능함

Layer

EC2 인스턴스 생성을 위한 틀(탬플릿의 개념)
OpsWorks 내장으로 Rails with Passenger, Java with Tomcat, Nodejs, RDS 등을 기본으로 지원하고, Custom하게 만들 수도 있음

내장 탬플릿으로 레이어를 생성하면 AWS에서 지원하는 Chef 레시피(Recipe)들이 기본적으로 들어가있다.(Chef 12의 경우는 없다고 하는데 실행해보지는 않음)

Opsworks Lifecycle Events

Layer들은 5개의 이벤트를 가지고 있음, 이벤트 발생시 각 이벤트마다 등록된 레시피(Recipe)가 실행됨

  1. Setup
    인스턴스 부팅이 완료된 후 발생
    수동으로 이벤트 발생 가능
    명렁 참고

  2. Configure
    스택의 모든 인스턴스들 중 어느 하나라도 아래 상황 중 하나의 경우에 해당할 경우, 모든 인스턴스에게 발생함

    • 인스턴스가 온라인 상태가 되었거나, 온라인 상태에서 벗어날때(leave the online)
    • 인스턴스가 EIP가 할당되거나, 할당이 취소될 때
    • ELB를 레이어에 연결하거나, 연결해제 할때
  3. Deploy
    Deploy Command를 실행했을 때 발생
    Setup이 완료된 후에 Deploy 레시피가 실행됨

  4. Undeploy
    앱을 지웠거나 Undeploy 명령을 실행 했을 때 발생

  5. Shutdown
    Opsworks에서 인스턴스를 종료하고, 실제로 EC2인스턴스가 종료하기전에 발생
    인스턴스를 리부팅할때는 어떤 이벤트도 발생하지 않음

AWS OpsWorks for Chef Automate

Chef Automate를 AWS에서 손쉽게 이용할 수 있는 서비스
현재(2017년 5월) US East (Northern Virginia), US West (Oregon) 및 Europe (Ireland) 지역에서만 이용 가능

Habitat(앱 빌드 및 패키징 자동화), InSpec(컴플라이언스 자동화)과 Chef를 함께 사용하는 CI(지속적 통합)서비스

Chef Automate AWS 블로그

KMS (Key Management Service)

데이터를 암호화할 때 사용하는 암호화 키를 쉽게 생성하고 제어할 수 있게 해주는 관리형 서비스

AWS product category AWS services integrated with KMS
Compute Amazon Lightsail*, Amazon EC2 SSM*, AWS Lambda
Storage & Content Delivery Amazon S3, Amazon EBS, AWS Import/Export Snowball, AWS Storage Gateway
Databases Amazon RDS, Amazon Redshift, AWS Database Migration Service
Developer Tools AWS CodeCommit*
Management Tools AWS CloudTrail
Analytics Amazon EMR, Amazon Kinesis Firehose
Application Services Amazon Elastic Transcoder, Amazon SES
Enterprise Applications Amazon WorkSpaces, Amazon WorkMail

KMS는 AWS SDK, the AWS Command Line Interface, RESTful API와 통합해서 사용

CloudTrail

  • CLoudTrail은 AWS 계정 사용에 대한 관리, 운영 감사, 취약점 감사등을 도와주는 서비스
  • AWS상의 서비스에 대한 로그, 지속적 모니터링, api사용 관련 이벤트등 제공

결론

AWS에는 훨씬 더 많은 서비스들이 존재하고 앞으로도 계속 생길 것입니다.
이번 AWS Summit 2017 in Seoul 도 참여 했었는데 새로운 서비스들이 등장하더군요.

AWS 자격증도 있던데 2년마다 갱신되고 상당히 힘들어보였습니다.
관심있으시면 한번 도전해보세요.

[adsense2]

Error occurs when start an instance AWS OpsWorks

Error occurs when start an instance AWS OpsWorks

When I start a new instance on OpsWorks Layers, I faced this error.

================================================================================
Recipe Compile Error in /var/lib/aws/opsworks/cache.stage2/cookbooks/aws/resources/cloudwatch.rb
================================================================================

NoMethodError
-------------
undefined method `property' for #&lt;Class:0x007f511b6ee538&gt;

Cookbook Trace:
---------------
/var/lib/aws/opsworks/cache.stage2/cookbooks/aws/resources/cloudwatch.rb:1:in `class_from_file'

Relevant File Content:
----------------------
/var/lib/aws/opsworks/cache.stage2/cookbooks/aws/resources/cloudwatch.rb:

1&gt;&gt; property :alarm_name, String, name_property: true
2: property :alarm_description, String
3: property :actions_enabled, TrueClass
4: property :ok_actions, Array, default: []
5: property :alarm_actions, Array, default: []
6: property :insufficient_data_actions, Array, default: []
7: property :metric_name, String
8: property :namespace, String
9: property :statistic, equal_to: %w(SampleCount Average Sum Minimum Maximum)
10: property :extended_statistic, String

I got a panic….
Because it certainly worked fine when I start an instance before a couple of hours…

I had found a solution.
Finally I found it.

That’s why AWS cookbook updated.

My OpsWorks system used chef11.
When AWS cookbook updated 6.1.0, it has used new method, property.

I specified a version of AWS cookbook on my Berkshelf

Finally it works well.

p80.pool.sks-keyservers.net: Host not found

AWS의 Opsworks에서 새로운 instances를 만들다가 만난 에러를 정리해둡니다.

AWS의 Opsworks 는 인스턴스를 새로 생성하면 등록되어있는 Chef Recipe 들을 자동으로 실행해주는 툴입니다.

이번에 Instance 한개를 추가로 생성하고, 그 Instance에 하나의 App 을 배포하려고 기존 Layer에서 추가로 Instance 를 생성하게 되었습니다.

그런데 갑자기 에러가 발생해서 로그를 봤더니 이런 로그가 있었습니다.

Mixlib::ShellOut::ShellCommandFailed
------------------------------------
execute[install-key 58118E89F3A912897C070ADBF76221572C52609D] (/var/lib/aws/opsworks/cache.stage2/cookbooks/apt/providers/repository.rb line 28) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '2'
---- Begin output of apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D ----
STDOUT: Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/tmp.YjqEGDmda9 --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D
?: p80.pool.sks-keyservers.net: Host not found
gpgkeys: HTTP fetch error 7: couldn't connect: Success
STDERR: gpg: requesting key 2C52609D from hkp server p80.pool.sks-keyservers.net
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0
---- End output of apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D ----
Ran apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D returned 2

Resource Declaration:
---------------------
# In /var/lib/aws/opsworks/cache.stage2/cookbooks/ops-docker/recipes/install.rb

4: apt_repository 'docker' do
5: uri node['docker']['package']['repo_url']
6: distribution node['docker']['package']['distribution']
7: components ['main']
8: keyserver node['docker']['package']['repo_keyserver']
9: key node['docker']['package']['repo_key']
10: end
11:

Compiled Resource:
------------------
# Declared in /var/lib/aws/opsworks/cache.stage2/cookbooks/ops-docker/recipes/install.rb:4:in `from_file'

apt_repository("docker") do
action :add
retries 0
retry_delay 2
cookbook_name "ops-docker"
recipe_name "install"
uri "https://apt.dockerproject.org/repo"
distribution "ubuntu-trusty"
components ["main"]
keyserver "hkp://p80.pool.sks-keyservers.net:80"
key "58118E89F3A912897C070ADBF76221572C52609D"
cache_rebuild true
end

[2017-05-03T09:17:52+00:00] INFO: Running queued delayed notifications before re-raising exception
[2017-05-03T09:17:52+00:00] ERROR: Running exception handlers
[2017-05-03T09:17:52+00:00] ERROR: Exception handlers complete
[2017-05-03T09:17:52+00:00] FATAL: Stacktrace dumped to /var/lib/aws/opsworks/cache.stage2/chef-stacktrace.out
[2017-05-03T09:17:52+00:00] ERROR: apt_repository[docker] (ops-docker::install line 4) had an error: Mixlib::ShellOut::ShellCommandFailed: execute[install-key 58118E89F3A912897C070ADBF76221572C52609D] (/var/lib/aws/opsworks/cache.stage2/cookbooks/apt/providers/repository.rb line 28) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '2'
---- Begin output of apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D ----
STDOUT: Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/tmp.YjqEGDmda9 --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D
?: p80.pool.sks-keyservers.net: Host not found
gpgkeys: HTTP fetch error 7: couldn't connect: Success
STDERR: gpg: requesting key 2C52609D from hkp server p80.pool.sks-keyservers.net
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0
---- End output of apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D ----
Ran apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D returned 2
[2017-05-03T09:17:53+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)

해서 검색을 시작했습니다.
저는 OpsWorksDocker에 서툴러서 뭔 실수를 했나 싶었는데 결과는…
그냥 단순히 서버 다운… OTL.

p80.pool.sks-keyservers.net: Host not found
gpgkeys: HTTP fetch error 7: couldn’t connect: Success

그냥 저 서버가 죽은거 였네요.

저 서버가 Docker설치시 기본으로 바로보는 PGP key server인 듯..
아래 링크가 이 에러와 관련된 Thread입니다.

Key server down for get.docker.com · Issue #13555 · moby/moby · GitHub

여기 가보면 kris라는 사람이
기존 Docker가 사용하는 서버주소를
From,

p80.pool.sks-keyservers.net

To,

hkp://keyserver.ubuntu.com:80

로 변경해주라고 답을 달아놨더군요.

 

결론

아무튼 이 버그의 결론은,
잠시뒤에 다시 시도 해본다;;;;

서버가 살아날 시간을 주는 것입니다;;