Kubernetes on AWS

 

일단 Kubernetes의 개념에서 알아 봤듯이

Kubenetes에는 한개의 마스터노드와 여러개의 워커노드가 통신을 합니다.

그러기에 기본적으로 마스터노드/워커노드 역할을 할 서버를 세팅해 줘야겠죠!

 

 

여기서 Kops나 Kubespray등 다양한 방법으로 Kubernetes 클러스터를 구성 해 줄수있는데

저는 Kops를 이용하여 구성을 해보도록 하겠습니다.

 

docker가 설치되어져있다는 전제하에 순서는 다음과 같습니다.

 

1. kubectl 설치

2. kops 설치

3. 클러스터 구성

 

 

1. kubectl 설치 - Binary 를 이용한 설치

curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl

 

특정 버전을 다운받으려면 다음과 같은 형태로 버전을 입력해주면 됩니다.

curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
#  install kubectl 
[ec2-user@ip-172-31-37-116 bin]$ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl

# 권한설정
[ec2-user@ip-172-31-37-116 bin]$ chmod +x ./kubectl

# 경로설정
[ec2-user@ip-172-31-37-116 bin]$ sudo mv ./kubectl /usr/local/bin/kubectl

# 설치확인
[ec2-user@ip-172-31-37-116 bin]$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", BuildDate:"2020-04-16T11:56:40Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

 

설치가 잘 된것을 확인하실 수 있습니다.

 

번외로 Package를 이용한 설치 혹은 다른 OS를 사용하시는 분들은 아래의 문서를 참고하시기 바랍니다.

https://kubernetes.io/docs/tasks/tools/install-kubectl/

 

2. kops 설치

kops도 마찬가지로 바이너리를 이용하여 설치를 진행하겠습니다.

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64

 

특정 버전을 다운받으려면 다음과 같은 형태로 버전을 입력해주면 됩니다.

curl -LO  https://github.com/kubernetes/kops/releases/download/1.15.0/kops-linux-amd64

 

# 1. install Kops
[root@ip-172-31-37-116 ~]# curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64

# 권한설정
[root@ip-172-31-37-116 ~]# chmod +x kops-linux-amd64

# 경로설정
[root@ip-172-31-37-116 ~]# mv kops-linux-amd64 /usr/local/bin/kops

# 설치확인
[root@ip-172-31-37-116 ~]# kops version
Version 1.16.1 (git-d1b07f7fd6)

 

 

3. 클러스터 구성

 

클러스터를 구성하려면 여러개의 단계가 존재하는데요

aws를 기준으로 설명드리자면 클러스터는 IP가 아닌 DNS로 통신을 하기때문에 먼저 DNS를 설정해준 후 클러스터 관리를 위해 상태나 혹은 키 정보들을 저장해줄 스토리지를 구성해줘야 합니다.

 

저는 aws위에서 관리를 하기에 DNS설정으로는

Route53, 그리고 스토리지로는 S3를 이용하여 구성해보도록 하겠습니다.

 

3-1. Route53 구성

( 이부분 작성본이 사라져서 추후 업데이트 하겠습니다ㅜㅜ)

 

3-2. S3구성

# Create Bucket aws s3api create-bucket \ --bucket prefix-example-com-state-store \ --region ap-northeast-2 # S3 versioning aws s3api put-bucket-versioning \ --bucket prefix-example-com-state-store \ --versioning-configuration Status=Enabled

 

3-3. 환경변수 설정 및 ssh key pair 생성

aws API를 이용하기위한 변수설정

aws API를 이용하기위한 변수설정

[root@ip-172-31-37-116 ~]# export AWS_ACCESS_KEY_ID=$(aws configure get aws_access_key_id)
[root@ip-172-31-37-116 ~]# export AWS_SECRET_ACCESS_KEY=$(aws configure get aws_secret_access_key)

# 사전에 ssh-keygen을 이용하여 키를 생성해줍니다. 
[root@ip-172-31-37-116 ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:BTjgg7iUAAIQRTCbpBikyL1b6mQfNZoRwTPE1lR/fQQ root@ip-172-31-37-116.ap-northeast-2.compute.internal
The key's randomart image is:


# /root/.ssh/ 해당경로로 들어가보시면 key가 생성된 것을 보실 수 있습니다!

 

 

3-4. 클러스터 설정구성

# kops를 이용하여 클러스터를 생성해봅시다.

[root@ip-172-31-37-116 ~]# kops create cluster --zones ap-northeast-2c ${NAME}
I0430 05:04:27.012121    7656 create_cluster.go:562] Inferred --cloud=aws from zone "ap-northeast-2c"
I0430 05:04:27.057539    7656 subnets.go:184] Assigned CIDR 172.20.32.0/19 to subnet ap-northeast-2c
I0430 05:04:28.477517    7656 create_cluster.go:1568] Using SSH public key: /root/.ssh/id_rsa.pub
Previewing changes that will be made:


I0430 05:04:31.177598    7656 apply_cluster.go:556] Gossip DNS: skipping DNS validation
I0430 05:04:31.229426    7656 executor.go:103] Tasks: 0 done / 92 total; 44 can run
I0430 05:04:32.016602    7656 executor.go:103] Tasks: 44 done / 92 total; 24 can run
I0430 05:04:32.428758    7656 executor.go:103] Tasks: 68 done / 92 total; 20 can run
I0430 05:04:32.503308    7656 executor.go:103] Tasks: 88 done / 92 total; 3 can run
W0430 05:04:32.570352    7656 keypair.go:140] Task did not have an address: *awstasks.LoadBalancer {"Name":"api.kbseo.k8s.local","Lifecycle":"Sync","LoadBalancerName":"api-kbseo-k8s-local-a1vmch","DNSName":null,"HostedZoneId":null,"Subnets":[{"Name":"ap-northeast-2c.kbseo.k8s.local","ShortName":"ap-northeast-2c","Lifecycle":"Sync","ID":null,"VPC":{"Name":"kbseo.k8s.local","Lifecycle":"Sync","ID":null,"CIDR":"172.20.0.0/16","EnableDNSHostnames":true,"EnableDNSSupport":true,"Shared":false,"Tags":{"KubernetesCluster":"kbseo.k8s.local","Name":"kbseo.k8s.local","kubernetes.io/cluster/kbseo.k8s.local":"owned"}},"AvailabilityZone":"ap-northeast-2c","CIDR":"172.20.32.0/19","Shared":false,"Tags":{"KubernetesCluster":"kbseo.k8s.local","Name":"ap-northeast-2c.kbseo.k8s.local","SubnetType":"Public","kubernetes.io/cluster/kbseo.k8s.local":"owned","kubernetes.io/role/elb":"1"}}],"SecurityGroups":[{"Name":"api-elb.kbseo.k8s.local","Lifecycle":"Sync","ID":null,"Description":"Security group for api ELB","VPC":{"Name":"kbseo.k8s.local","Lifecycle":"Sync","ID":null,"CIDR":"172.20.0.0/16","EnableDNSHostnames":true,"EnableDNSSupport":true,"Shared":false,"Tags":{"KubernetesCluster":"kbseo.k8s.local","Name":"kbseo.k8s.local","kubernetes.io/cluster/kbseo.k8s.local":"owned"}},"RemoveExtraRules":["port=443"],"Shared":null,"Tags":{"KubernetesCluster":"kbseo.k8s.local","Name":"api-elb.kbseo.k8s.local","kubernetes.io/cluster/kbseo.k8s.local":"owned"}}],"Listeners":{"443":{"InstancePort":443,"SSLCertificateID":""}},"Scheme":null,"HealthCheck":{"Target":"SSL:443","HealthyThreshold":2,"UnhealthyThreshold":2,"Interval":10,"Timeout":5},"AccessLog":null,"ConnectionDraining":null,"ConnectionSettings":{"IdleTimeout":300},"CrossZoneLoadBalancing":{"Enabled":false},"SSLCertificateID":"","Tags":{"KubernetesCluster":"kbseo.k8s.local","Name":"api.kbseo.k8s.local","kubernetes.io/cluster/kbseo.k8s.local":"owned"}}
I0430 05:04:32.755402    7656 executor.go:103] Tasks: 91 done / 92 total; 1 can run
I0430 05:04:32.840253    7656 executor.go:103] Tasks: 92 done / 92 total; 0 can run
Will create resources:
  AutoscalingGroup/master-ap-northeast-2c.masters.kbseo.k8s.local
      Granularity             1Minute
      LaunchConfiguration     name:master-ap-northeast-2c.masters.kbseo.k8s.local
      MaxSize                 1
      Metrics                 [GroupDesiredCapacity, GroupInServiceInstances, GroupMaxSize, GroupMinSize, GroupPendingInstances, GroupStandbyInstances, GroupTerminatingInstances, GroupTotalInstances]
      MinSize                 1
      Subnets                 [name:ap-northeast-2c.kbseo.k8s.local]
      SuspendProcesses        []
      Tags                    {Name: master-ap-northeast-2c.masters.kbseo.k8s.local, k8s.io/role/master: 1, kops.k8s.io/instancegroup: master-ap-northeast-2c, k8s.io/cluster-autoscaler/node-template/label/kops.k8s.io/instancegroup: master-ap-northeast-2c, KubernetesCluster: kbseo.k8s.local}


  AutoscalingGroup/nodes.kbseo.k8s.local
      Granularity             1Minute
      LaunchConfiguration     name:nodes.kbseo.k8s.local
      MaxSize                 2
      Metrics                 [GroupDesiredCapacity, GroupInServiceInstances, GroupMaxSize, GroupMinSize, GroupPendingInstances, GroupStandbyInstances, GroupTerminatingInstances, GroupTotalInstances]
      MinSize                 2
      Subnets                 [name:ap-northeast-2c.kbseo.k8s.local]
      SuspendProcesses        []
      Tags                    {k8s.io/cluster-autoscaler/node-template/label/kops.k8s.io/instancegroup: nodes, KubernetesCluster: kbseo.k8s.local, Name: nodes.kbseo.k8s.local, k8s.io/role/node: 1, kops.k8s.io/instancegroup: nodes}


  DHCPOptions/kbseo.k8s.local
      DomainName              ap-northeast-2.compute.internal
      DomainNameServers       AmazonProvidedDNS
      Shared                  false
      Tags                    {Name: kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned}


  EBSVolume/c.etcd-events.kbseo.k8s.local
      AvailabilityZone        ap-northeast-2c
      Encrypted               false
      SizeGB                  20
      Tags                    {k8s.io/etcd/events: c/c, k8s.io/role/master: 1, kubernetes.io/cluster/kbseo.k8s.local: owned, Name: c.etcd-events.kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local}
      VolumeType              gp2


  EBSVolume/c.etcd-main.kbseo.k8s.local
      AvailabilityZone        ap-northeast-2c
      Encrypted               false
      SizeGB                  20
      Tags                    {k8s.io/etcd/main: c/c, k8s.io/role/master: 1, kubernetes.io/cluster/kbseo.k8s.local: owned, Name: c.etcd-main.kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local}
      VolumeType              gp2


  IAMInstanceProfile/masters.kbseo.k8s.local
      Shared                  false


  IAMInstanceProfile/nodes.kbseo.k8s.local
      Shared                  false


  IAMInstanceProfileRole/masters.kbseo.k8s.local
      InstanceProfile         name:masters.kbseo.k8s.local id:masters.kbseo.k8s.local
      Role                    name:masters.kbseo.k8s.local


  IAMInstanceProfileRole/nodes.kbseo.k8s.local
      InstanceProfile         name:nodes.kbseo.k8s.local id:nodes.kbseo.k8s.local
      Role                    name:nodes.kbseo.k8s.local


  IAMRole/masters.kbseo.k8s.local
      ExportWithID            masters


  IAMRole/nodes.kbseo.k8s.local
      ExportWithID            nodes


  IAMRolePolicy/masters.kbseo.k8s.local
      Role                    name:masters.kbseo.k8s.local


  IAMRolePolicy/nodes.kbseo.k8s.local
      Role                    name:nodes.kbseo.k8s.local


  InternetGateway/kbseo.k8s.local
      VPC                     name:kbseo.k8s.local
      Shared                  false
      Tags                    {Name: kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned}


  Keypair/apiserver-aggregator
      Signer                  name:apiserver-aggregator-ca id:cn=apiserver-aggregator-ca
      Subject                 cn=aggregator
      Type                    client
      Format                  v1alpha2


  Keypair/apiserver-aggregator-ca
      Subject                 cn=apiserver-aggregator-ca
      Type                    ca
      Format                  v1alpha2


  Keypair/apiserver-proxy-client
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=apiserver-proxy-client
      Type                    client
      Format                  v1alpha2


  Keypair/ca
      Subject                 cn=kubernetes
      Type                    ca
      Format                  v1alpha2


  Keypair/etcd-clients-ca
      Subject                 cn=etcd-clients-ca
      Type                    ca
      Format                  v1alpha2


  Keypair/etcd-manager-ca-events
      Subject                 cn=etcd-manager-ca-events
      Type                    ca
      Format                  v1alpha2


  Keypair/etcd-manager-ca-main
      Subject                 cn=etcd-manager-ca-main
      Type                    ca
      Format                  v1alpha2


  Keypair/etcd-peers-ca-events
      Subject                 cn=etcd-peers-ca-events
      Type                    ca
      Format                  v1alpha2


  Keypair/etcd-peers-ca-main
      Subject                 cn=etcd-peers-ca-main
      Type                    ca
      Format                  v1alpha2


  Keypair/kops
      Signer                  name:ca id:cn=kubernetes
      Subject                 o=system:masters,cn=kops
      Type                    client
      Format                  v1alpha2


  Keypair/kube-controller-manager
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=system:kube-controller-manager
      Type                    client
      Format                  v1alpha2


  Keypair/kube-proxy
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=system:kube-proxy
      Type                    client
      Format                  v1alpha2


  Keypair/kube-scheduler
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=system:kube-scheduler
      Type                    client
      Format                  v1alpha2


  Keypair/kubecfg
      Signer                  name:ca id:cn=kubernetes
      Subject                 o=system:masters,cn=kubecfg
      Type                    client
      Format                  v1alpha2


  Keypair/kubelet
      Signer                  name:ca id:cn=kubernetes
      Subject                 o=system:nodes,cn=kubelet
      Type                    client
      Format                  v1alpha2


  Keypair/kubelet-api
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=kubelet-api
      Type                    client
      Format                  v1alpha2


  Keypair/master
      AlternateNames          [100.64.0.1, 127.0.0.1, api.internal.kbseo.k8s.local, api.kbseo.k8s.local, kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local]
      Signer                  name:ca id:cn=kubernetes
      Subject                 cn=kubernetes-master
      Type                    server
      Format                  v1alpha2


  LaunchConfiguration/master-ap-northeast-2c.masters.kbseo.k8s.local
      AssociatePublicIP       true
      IAMInstanceProfile      name:masters.kbseo.k8s.local id:masters.kbseo.k8s.local
      ImageID                 kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2020-01-17
      InstanceType            c4.large
      RootVolumeDeleteOnTermination    true
      RootVolumeSize          64
      RootVolumeType          gp2
      SSHKey                  name:kubernetes.kbseo.k8s.local-12:b8:34:12:0c:2d:97:b3:2e:3c:5b:98:2c:5c:70:a8 id:kubernetes.kbseo.k8s.local-12:b8:34:12:0c:2d:97:b3:2e:3c:5b:98:2c:5c:70:a8
      SecurityGroups          [name:masters.kbseo.k8s.local]
      SpotPrice               


  LaunchConfiguration/nodes.kbseo.k8s.local
      AssociatePublicIP       true
      IAMInstanceProfile      name:nodes.kbseo.k8s.local id:nodes.kbseo.k8s.local
      ImageID                 kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2020-01-17
      InstanceType            t2.medium
      RootVolumeDeleteOnTermination    true
      RootVolumeSize          128
      RootVolumeType          gp2
      SSHKey                  name:kubernetes.kbseo.k8s.local-12:b8:34:12:0c:2d:97:b3:2e:3c:5b:98:2c:5c:70:a8 id:kubernetes.kbseo.k8s.local-12:b8:34:12:0c:2d:97:b3:2e:3c:5b:98:2c:5c:70:a8
      SecurityGroups          [name:nodes.kbseo.k8s.local]
      SpotPrice               


  LoadBalancer/api.kbseo.k8s.local
      LoadBalancerName        api-kbseo-k8s-local-a1vmch
      Subnets                 [name:ap-northeast-2c.kbseo.k8s.local]
      SecurityGroups          [name:api-elb.kbseo.k8s.local]
      Listeners               {443: {"InstancePort":443,"SSLCertificateID":""}}
      HealthCheck             {"Target":"SSL:443","HealthyThreshold":2,"UnhealthyThreshold":2,"Interval":10,"Timeout":5}
      ConnectionSettings      {"IdleTimeout":300}
      CrossZoneLoadBalancing    {"Enabled":false}
      SSLCertificateID        
      Tags                    {Name: api.kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned}


  LoadBalancerAttachment/api-master-ap-northeast-2c
      LoadBalancer            name:api.kbseo.k8s.local id:api.kbseo.k8s.local
      AutoscalingGroup        name:master-ap-northeast-2c.masters.kbseo.k8s.local id:master-ap-northeast-2c.masters.kbseo.k8s.local


  ManagedFile/etcd-cluster-spec-events
      Location                backups/etcd/events/control/etcd-cluster-spec


  ManagedFile/etcd-cluster-spec-main
      Location                backups/etcd/main/control/etcd-cluster-spec


  ManagedFile/kbseo.k8s.local-addons-bootstrap
      Location                addons/bootstrap-channel.yaml


  ManagedFile/kbseo.k8s.local-addons-core.addons.k8s.io
      Location                addons/core.addons.k8s.io/v1.4.0.yaml


  ManagedFile/kbseo.k8s.local-addons-dns-controller.addons.k8s.io-k8s-1.12
      Location                addons/dns-controller.addons.k8s.io/k8s-1.12.yaml


  ManagedFile/kbseo.k8s.local-addons-dns-controller.addons.k8s.io-k8s-1.6
      Location                addons/dns-controller.addons.k8s.io/k8s-1.6.yaml


  ManagedFile/kbseo.k8s.local-addons-dns-controller.addons.k8s.io-pre-k8s-1.6
      Location                addons/dns-controller.addons.k8s.io/pre-k8s-1.6.yaml


  ManagedFile/kbseo.k8s.local-addons-kops-controller.addons.k8s.io-k8s-1.16
      Location                addons/kops-controller.addons.k8s.io/k8s-1.16.yaml


  ManagedFile/kbseo.k8s.local-addons-kube-dns.addons.k8s.io-k8s-1.12
      Location                addons/kube-dns.addons.k8s.io/k8s-1.12.yaml


  ManagedFile/kbseo.k8s.local-addons-kube-dns.addons.k8s.io-k8s-1.6
      Location                addons/kube-dns.addons.k8s.io/k8s-1.6.yaml


  ManagedFile/kbseo.k8s.local-addons-kube-dns.addons.k8s.io-pre-k8s-1.6
      Location                addons/kube-dns.addons.k8s.io/pre-k8s-1.6.yaml


  ManagedFile/kbseo.k8s.local-addons-kubelet-api.rbac.addons.k8s.io-k8s-1.9
      Location                addons/kubelet-api.rbac.addons.k8s.io/k8s-1.9.yaml


  ManagedFile/kbseo.k8s.local-addons-limit-range.addons.k8s.io
      Location                addons/limit-range.addons.k8s.io/v1.5.0.yaml


  ManagedFile/kbseo.k8s.local-addons-rbac.addons.k8s.io-k8s-1.8
      Location                addons/rbac.addons.k8s.io/k8s-1.8.yaml


  ManagedFile/kbseo.k8s.local-addons-storage-aws.addons.k8s.io-v1.15.0
      Location                addons/storage-aws.addons.k8s.io/v1.15.0.yaml


  ManagedFile/kbseo.k8s.local-addons-storage-aws.addons.k8s.io-v1.6.0
      Location                addons/storage-aws.addons.k8s.io/v1.6.0.yaml


  ManagedFile/kbseo.k8s.local-addons-storage-aws.addons.k8s.io-v1.7.0
      Location                addons/storage-aws.addons.k8s.io/v1.7.0.yaml


  ManagedFile/manifests-etcdmanager-events
      Location                manifests/etcd/events.yaml


  ManagedFile/manifests-etcdmanager-main
      Location                manifests/etcd/main.yaml


  Route/0.0.0.0/0
      RouteTable              name:kbseo.k8s.local
      CIDR                    0.0.0.0/0
      InternetGateway         name:kbseo.k8s.local


  RouteTable/kbseo.k8s.local
      VPC                     name:kbseo.k8s.local
      Shared                  false
      Tags                    {Name: kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned, kubernetes.io/kops/role: public}


  RouteTableAssociation/ap-northeast-2c.kbseo.k8s.local
      RouteTable              name:kbseo.k8s.local
      Subnet                  name:ap-northeast-2c.kbseo.k8s.local


  SSHKey/kubernetes.kbseo.k8s.local-12:b8:34:12:0c:2d:97:b3:2e:3c:5b:98:2c:5c:70:a8
      KeyFingerprint          cd:b0:00:ed:d3:5a:e4:b3:17:51:80:87:9c:50:48:31


  Secret/admin


  Secret/kube


  Secret/kube-proxy


  Secret/kubelet


  Secret/system:controller_manager


  Secret/system:dns


  Secret/system:logging


  Secret/system:monitoring


  Secret/system:scheduler


  SecurityGroup/api-elb.kbseo.k8s.local
      Description             Security group for api ELB
      VPC                     name:kbseo.k8s.local
      RemoveExtraRules        [port=443]
      Tags                    {Name: api-elb.kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned}


  SecurityGroup/masters.kbseo.k8s.local
      Description             Security group for masters
      VPC                     name:kbseo.k8s.local
      RemoveExtraRules        [port=22, port=443, port=2380, port=2381, port=4001, port=4002, port=4789, port=179]
      Tags                    {KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned, Name: masters.kbseo.k8s.local}


  SecurityGroup/nodes.kbseo.k8s.local
      Description             Security group for nodes
      VPC                     name:kbseo.k8s.local
      RemoveExtraRules        [port=22]
      Tags                    {kubernetes.io/cluster/kbseo.k8s.local: owned, Name: nodes.kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local}


  SecurityGroupRule/all-master-to-master
      SecurityGroup           name:masters.kbseo.k8s.local
      SourceGroup             name:masters.kbseo.k8s.local


  SecurityGroupRule/all-master-to-node
      SecurityGroup           name:nodes.kbseo.k8s.local
      SourceGroup             name:masters.kbseo.k8s.local


  SecurityGroupRule/all-node-to-node
      SecurityGroup           name:nodes.kbseo.k8s.local
      SourceGroup             name:nodes.kbseo.k8s.local


  SecurityGroupRule/api-elb-egress
      SecurityGroup           name:api-elb.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Egress                  true


  SecurityGroupRule/https-api-elb-0.0.0.0/0
      SecurityGroup           name:api-elb.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Protocol                tcp
      FromPort                443
      ToPort                  443


  SecurityGroupRule/https-elb-to-master
      SecurityGroup           name:masters.kbseo.k8s.local
      Protocol                tcp
      FromPort                443
      ToPort                  443
      SourceGroup             name:api-elb.kbseo.k8s.local


  SecurityGroupRule/icmp-pmtu-api-elb-0.0.0.0/0
      SecurityGroup           name:api-elb.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Protocol                icmp
      FromPort                3
      ToPort                  4


  SecurityGroupRule/master-egress
      SecurityGroup           name:masters.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Egress                  true


  SecurityGroupRule/node-egress
      SecurityGroup           name:nodes.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Egress                  true


  SecurityGroupRule/node-to-master-tcp-1-2379
      SecurityGroup           name:masters.kbseo.k8s.local
      Protocol                tcp
      FromPort                1
      ToPort                  2379
      SourceGroup             name:nodes.kbseo.k8s.local


  SecurityGroupRule/node-to-master-tcp-2382-4000
      SecurityGroup           name:masters.kbseo.k8s.local
      Protocol                tcp
      FromPort                2382
      ToPort                  4000
      SourceGroup             name:nodes.kbseo.k8s.local


  SecurityGroupRule/node-to-master-tcp-4003-65535
      SecurityGroup           name:masters.kbseo.k8s.local
      Protocol                tcp
      FromPort                4003
      ToPort                  65535
      SourceGroup             name:nodes.kbseo.k8s.local


  SecurityGroupRule/node-to-master-udp-1-65535
      SecurityGroup           name:masters.kbseo.k8s.local
      Protocol                udp
      FromPort                1
      ToPort                  65535
      SourceGroup             name:nodes.kbseo.k8s.local


  SecurityGroupRule/ssh-external-to-master-0.0.0.0/0
      SecurityGroup           name:masters.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Protocol                tcp
      FromPort                22
      ToPort                  22


  SecurityGroupRule/ssh-external-to-node-0.0.0.0/0
      SecurityGroup           name:nodes.kbseo.k8s.local
      CIDR                    0.0.0.0/0
      Protocol                tcp
      FromPort                22
      ToPort                  22


  Subnet/ap-northeast-2c.kbseo.k8s.local
      ShortName               ap-northeast-2c
      VPC                     name:kbseo.k8s.local
      AvailabilityZone        ap-northeast-2c
      CIDR                    172.20.32.0/19
      Shared                  false
      Tags                    {KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned, SubnetType: Public, kubernetes.io/role/elb: 1, Name: ap-northeast-2c.kbseo.k8s.local}


  VPC/kbseo.k8s.local
      CIDR                    172.20.0.0/16
      EnableDNSHostnames      true
      EnableDNSSupport        true
      Shared                  false
      Tags                    {Name: kbseo.k8s.local, KubernetesCluster: kbseo.k8s.local, kubernetes.io/cluster/kbseo.k8s.local: owned}


  VPCDHCPOptionsAssociation/kbseo.k8s.local
      VPC                     name:kbseo.k8s.local
      DHCPOptions             name:kbseo.k8s.local


Must specify --yes to apply changes


Cluster configuration has been created.


Suggestions:
* list clusters with: kops get cluster
* edit this cluster with: kops edit cluster kbseo.k8s.local
* edit your node instance group: kops edit ig --name=kbseo.k8s.local nodes
* edit your master instance group: kops edit ig --name=kbseo.k8s.local master-ap-northeast-2c


Finally configure your cluster with: kops update cluster --name kbseo.k8s.local --yes

 

자 클러스터가 만들어졌는지 확인해볼까요?

[root@ip-172-31-37-116 ~]# kops get ig --name ${NAME}
NAME            ROLE    MACHINETYPE    MIN    MAX    ZONES
master-ap-northeast-2c    Master    c4.large    1    1    ap-northeast-2c
nodes            Node    t2.medium    2    2    ap-northeast-2c

# 여기에서 주의할 점은 실제 리소스가 아닌 설정만을 생성한다는 점 입니다.
# kops update cluster로 실제 구성이 가능합니다.

 

기본으로 c4.large타입과 t2.medium이 생성되는데 

요금의 압박이 있기에 인스턴스 사이즈를 변경해줍니다.

 

[root@ip-172-31-37-116 ~]# kops edit ig master-ap-northeast-2c --name ${NAME}


apiVersion: kops.k8s.io/v1alpha2
ps edit ig nodes --name ${NAME}
kind: InstanceGroup
metadata:
  creationTimestamp: "2020-04-30T05:04:28Z"
  labels:
    kops.k8s.io/cluster: kbseo.k8s.local
  name: master-ap-northeast-2c
spec:
  image: kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2020-01-17
  machineType: c4.large     <------- 원하고자 하는 instance type
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: master-ap-northeast-2c
  role: Master
  subnets:
  - ap-northeast-2c




[root@ip-172-31-37-116 ~]# kops edit ig nodes --name ${NAME}

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: "2020-04-30T05:04:28Z"
  generation: 1
  labels:
    kops.k8s.io/cluster: kbseo.k8s.local
  name: nodes
spec:
  image: kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2020-01-17
  machineType: t3.small
  maxSize: 2
  minSize: 2
  nodeLabels:
    kops.k8s.io/instancegroup: nodes
  role: Node
  subnets:
  - ap-northeast-2c
~                    



# 확인
[root@ip-172-31-37-116 ~]# kops get ig --name ${NAME}
NAME            ROLE    MACHINETYPE    MIN    MAX    ZONES
master-ap-northeast-2c    Master    t2.small    1    1    ap-northeast-2c
nodes            Node    t2.small    2    2    ap-northeast-2c

[root@ip-172-31-37-116 ~]# kops update cluster ${NAME} --yes
I0430 06:26:24.977771    8160 apply_cluster.go:556] Gossip DNS: skipping DNS validation
I0430 06:26:25.625424    8160 executor.go:103] Tasks: 0 done / 92 total; 44 can run
I0430 06:26:26.447564    8160 executor.go:103] Tasks: 44 done / 92 total; 24 can run
I0430 06:26:27.165011    8160 executor.go:103] Tasks: 68 done / 92 total; 20 can run
I0430 06:26:27.415603    8160 executor.go:103] Tasks: 88 done / 92 total; 3 can run
I0430 06:26:27.586632    8160 executor.go:103] Tasks: 91 done / 92 total; 1 can run
I0430 06:26:27.675721    8160 executor.go:103] Tasks: 92 done / 92 total; 0 can run
I0430 06:26:27.768309    8160 update_cluster.go:305] Exporting kubecfg for cluster
kops has set your kubectl context to kbseo.k8s.local


Cluster changes have been applied to the cloud.




Changes may require instances to restart: kops rolling-update cluster


[root@ip-172-31-37-116 ~]#
[root@ip-172-31-37-116 ~]# kops rolling-update cluster
Using cluster from kubectl context: kbseo.k8s.local


NAME            STATUS        NEEDUPDATE    READY    MIN    MAX    NODES
master-ap-northeast-2c    NeedsUpdate    1        0    1    1    1
nodes            NeedsUpdate    2        0    2    2    2

 

 

edit 명령어를 통해 리소스들을 수정해 줄 수 있습니다.

 

[root@ip-172-31-37-116 ~]# kops edit cluster ${NAME}

Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: kops.k8s.io/v1alpha2
kind: Cluster
metadata:
  creationTimestamp: "2020-04-30T05:04:28Z"
  name: kbseo.k8s.local
spec:
  api:
    loadBalancer:
      type: Public
  authorization:
    rbac: {}
  channel: stable
  cloudProvider: aws
  configBase: s3://kubernetes-aws-kbseo-io/kbseo.k8s.local
  etcdClusters:
  - cpuRequest: 200m
    etcdMembers:
    - instanceGroup: master-ap-northeast-2c
      name: c
    memoryRequest: 100Mi
    name: main
  - cpuRequest: 100m
    etcdMembers:
    - instanceGroup: master-ap-northeast-2c
      name: c
    memoryRequest: 100Mi
    name: events
  iam:
    allowContainerRegistry: true
    legacy: false
  kubelet:
    anonymousAuth: false
  kubernetesApiAccess:
  - 0.0.0.0/0
  kubernetesVersion: 1.16.8
  masterInternalName: api.internal.kbseo.k8s.local
  masterPublicName: api.kbseo.k8s.local
  networkCIDR: 172.20.0.0/16
  networking:
    kubenet: {}
  nonMasqueradeCIDR: 100.64.0.0/10
  sshAccess:
  - 0.0.0.0/0
  subnets:
  - cidr: 172.20.32.0/19
    name: ap-northeast-2c
    type: Public
    zone: ap-northeast-2c
  topology:
    dns:
      type: Public
    masters: public
    nodes: public

 

3-4. 클러스터 생성

 

실제 리소스들을 한번 만들어볼까요?

 

[root@ip-172-31-37-116 ~]# kops update cluster ${NAME} --yes

Cluster is starting.  It should be ready in a few minutes.


Suggestions:
* validate cluster: kops validate cluster
* list nodes: kubectl get nodes --show-labels
* ssh to the master: ssh -i ~/.ssh/id_rsa admin@api.kbseo.k8s.local
* 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/operations/addons.md.

 

완료되는데 까지 시간이 조금 걸립니다 ㅎ.ㅎ

 

번외로 

kops delete cluster --name ${NAME} --yes

해당 명령어를 통해 클러스터를 삭제시킬 수 있습니다.

 

 

 

참조

https://kubernetes.io/ko/docs/setup/production-environment/tools/kops/

 

 

상황 

    PTR 등록 요청 후  nslookup/ dig를 이용하여 질의시 요청했던 IP와 다르게 보이는 현상

내용 요약 (IP/도메인은 임의)

 

 

#1. 요청내용

49.50.160.1 -> spam1.kbseo.com

49.50.160.2 -> spam2.kbseo.com

 

#2. 해당 답변내용

; <<>> DiG 9.10.6 <<>> @8.8.8.8 -x 49.50.160.2

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34381

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 512



;; QUESTION SECTION:

;35.160.50.49.in-addr.arpa.INPTR



;; ANSWER SECTION:

35.160.50.49.in-addr.arpa. 14399 INPTRspam2.kkbseo.com.



;; Query time: 139 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; WHEN: Fri Mar 27 18:31:01 KST 2020

;; MSG SIZE rcvd: 86







; <<>> DiG 9.10.6 <<>> @8.8.8.8 -x 49.50.160.1

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22098

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 512





;; QUESTION SECTION:

;36.160.50.49.in-addr.arpa.INPTR



;; ANSWER SECTION:

36.160.50.49.in-addr.arpa. 14399 INPTRspam1.kbseo.com.



;; Query time: 82 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; WHEN: Fri Mar 27 18:31:25 KST 2020

;; MSG SIZE rcvd: 86

 

#3. nslookup 및 dig를 이용하여 질의

#nslookup

[root@tktlkdd01 ~]# nslookup spam1.kbseo.com

Server:10.250.255.11

Address:10.250.255.11#53



Non-authoritative answer:

Name:spam1.hanatour.com

Address: 49.50.160.2
#dig

root@tktlkdd01 ~]# dig @222.122.70.251 spam1.kbseo.com





; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.el6_10.3 <<>> @222.122.70.251 spam1.hanatour.com

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18750

;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 6, ADDITIONAL: 2





;; QUESTION SECTION:

;spam1.kbseo.com.INA





;; ANSWER SECTION:

spam1.hanatour.com.600INA49.50.160.2





;; Query time: 4 msec

;; SERVER: 222.122.70.251#53(222.122.70.251)

;; WHEN: Mon Apr 27 15:34:26 2020

;; MSG SIZE rcvd: 218

 

--> 해당내용 답변

A 레코드로 조회해서 생기는 일.

 

A 레코드 -> 도메인과 ip주소를 매핑한 정보
PTR 레코드 -> 역으로 ip주소를 도메인과 매핑한 정보

 

즉 PTR레코드 즉 ip로 조회해 봤을 시 해당 ip에 매핑된 도메인 정보가 출력

하지만 A래코드, 도메인으로 조회시 도메인과 매핑된 ip가 출력

 

이 과정에서 PTR등록은 정상적으로 되었지만 A레코드등록 시 반대로 등록 된 결과.

 

 

# PTR 값으로 조회

[root@tktlkdd01 ~]# dig @222.122.70.251 -x 49.50.160.2





; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.el6_10.3 <<>> @222.122.70.251 -x 49.50.160.35

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14642

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 0





;; QUESTION SECTION:

;35.160.50.49.in-addr.arpa.    IN    PTR





;; ANSWER SECTION:

35.160.50.49.in-addr.arpa. 9461    IN    PTR    spam2.kbseo.com.





;; AUTHORITY SECTION:

160.50.49.in-addr.arpa.    167861    IN    NS    ns2c1.ncloud-dns.com.

160.50.49.in-addr.arpa.    167861    IN    NS    ns3c1.ncloud-dns.com.

160.50.49.in-addr.arpa.    167861    IN    NS    ns4c1.ncloud-dns.com.

160.50.49.in-addr.arpa.    167861    IN    NS    ns1c1.ncloud-dns.com.





;; Query time: 3 msec

;; SERVER: 222.122.70.251#53(222.122.70.251)

;; WHEN: Mon Apr 27 16:50:21 2020

;; MSG SIZE  rcvd: 166

 

# 도메인으로 조회

[root@tktlkdd01 ~]# dig @222.122.70.251 spam1.kbseo.com





; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.el6_10.3 <<>> @222.122.70.251 spam1.kbseo.com

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 273

;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 6, ADDITIONAL: 2





;; QUESTION SECTION:

;spam1.kbseo.com.        IN    A





;; ANSWER SECTION:

spam1.kbseo.com.    600    IN    A    49.50.160.2





;; Query time: 4 msec

;; SERVER: 222.122.70.251#53(222.122.70.251)

;; WHEN: Mon Apr 27 16:45:42 2020

;; MSG SIZE  rcvd: 218

 

 

 

 

Dig란?

dig는 Domain Information Groper의 약자로 네임서버로 부터 정보를 가져올 수 있는 툴 입니다.

 

보통 도메인 네임에 대한 DNS 질의응답이 정상적으로 이루어지는지를 확인하는 경우에 많이 쓰입니다!

 

dig는 bind-utils 패키지에 속한 유틸리티이기에 해달 패키지를 먼저 설치해줘야합니다.

$ yum install bind-utils

 

Dig 사용법

[root@kbseo-test1 stlapp]# dig <@server> <domain> <query type>

 

  • query type

    • a : 네트워크 주소

    • mx : 도메인의 메일 서버 주소

    • ns : 도메인의 권한 네임서버 정보

    • soa : 도메인 zone 파일 상단의 source of authority 레코드

 

1. dig domain

도메인 주소로 검색을 하면 /etc/resolv.conf 에 등록된 네임서버를 이용하여 도메인을 조회합니다.

 

[root@kbseo-test1 stlapp]# dig google.com





; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> google.com

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44148

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 9





;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 4096

;; QUESTION SECTION:

;google.com.            IN    A





;; ANSWER SECTION:

google.com.        205    IN    A    172.217.161.78





;; AUTHORITY SECTION:

google.com.        161857    IN    NS    ns2.google.com.

google.com.        161857    IN    NS    ns3.google.com.

google.com.        161857    IN    NS    ns4.google.com.

google.com.        161857    IN    NS    ns1.google.com.





;; ADDITIONAL SECTION:

ns1.google.com.        161873    IN    A    216.239.32.10

ns2.google.com.        161860    IN    A    216.239.34.10

ns3.google.com.        162712    IN    A    216.239.36.10

ns4.google.com.        161860    IN    A    216.239.38.10

ns1.google.com.        161933    IN    AAAA    2001:4860:4802:32::a

ns2.google.com.        161862    IN    AAAA    2001:4860:4802:34::a

ns3.google.com.        162030    IN    AAAA    2001:4860:4802:36::a

ns4.google.com.        161933    IN    AAAA    2001:4860:4802:38::a





;; Query time: 1 msec

;; SERVER: 168.126.63.1#53(168.126.63.1)

;; WHEN: Mon Apr 27 17:07:29 KST 2020

;; MSG SIZE  rcvd: 303

 

 

 

2. dig <네임서버> <도메인>

앞에 입력해준 네임서버를 이용하여 도메인을 조회합니다.

 

[root@kbseo-test1 stlapp]# dig @8.8.8.8 google.com





; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @8.8.8.8 google.com

; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48238

;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1





;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 512

;; QUESTION SECTION:

;google.com.            IN    A





;; ANSWER SECTION:

google.com.        163    IN    A    172.217.31.142





;; Query time: 37 msec

;; SERVER: 8.8.8.8#53(8.8.8.8)

;; WHEN: Mon Apr 27 17:09:56 KST 2020

;; MSG SIZE  rcvd: 55

 

 

3. dig <도메인> +trace

DNS질의 추적용으로 쓰입니다.

 

[root@kbseo-test1 stlapp]# dig google.com +trace





; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> google.com +trace

;; global options: +cmd

.            507078    IN    NS    i.root-servers.net.

.            507078    IN    NS    g.root-servers.net.

.            507078    IN    NS    f.root-servers.net.

.            507078    IN    NS    a.root-servers.net.

.            507078    IN    NS    h.root-servers.net.

.            507078    IN    NS    c.root-servers.net.

.            507078    IN    NS    l.root-servers.net.

.            507078    IN    NS    b.root-servers.net.

.            507078    IN    NS    k.root-servers.net.

.            507078    IN    NS    e.root-servers.net.

.            507078    IN    NS    m.root-servers.net.

.            507078    IN    NS    d.root-servers.net.

.            507078    IN    NS    j.root-servers.net.

;; Received 811 bytes from 168.126.63.1#53(168.126.63.1) in 1 ms





com.            172800    IN    NS    f.gtld-servers.net.

com.            172800    IN    NS    i.gtld-servers.net.

com.            172800    IN    NS    h.gtld-servers.net.

com.            172800    IN    NS    c.gtld-servers.net.

com.            172800    IN    NS    k.gtld-servers.net.

com.            172800    IN    NS    l.gtld-servers.net.

com.            172800    IN    NS    b.gtld-servers.net.

com.            172800    IN    NS    m.gtld-servers.net.

com.            172800    IN    NS    j.gtld-servers.net.

com.            172800    IN    NS    g.gtld-servers.net.

com.            172800    IN    NS    e.gtld-servers.net.

com.            172800    IN    NS    d.gtld-servers.net.

com.            172800    IN    NS    a.gtld-servers.net.

com.            86400    IN    DS    30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766

com.            86400    IN    RRSIG    DS 8 1 86400 20200509170000 20200426160000 48903 . dDn04wM4e7vHJI6SWe4V8ZvxxFg9xZ/PHYbwhSPoGbg39SZhhQpTSZ4v q9yuruhjs353ArcjoRQfyVSp+YArvQtWGTuItA1RlI6urwIOKcfyMYIr pacSXkpOM/xdQsLANrFoACcjsnwiwOlLJM7fYhJz7R3jybk2lJEBTkT3 DkXp69uGdw1DJJuMfX4FAuDf8hxX2TU5e3ehb1MW3I0QYvsrZnfNmmQM ZNDcClpTr0HgUM0XKdMqI1fiPiSP8ybup7wFiYhPhMKZF2UMYIcckf2i 2AWpcJvxrvWU/IVS9wmBx9u3ZvqvjRNQs3UoSQtq+SVAHsmbsv0hY+8b KWHirQ==

;; Received 1170 bytes from 192.36.148.17#53(i.root-servers.net) in 85 ms





google.com.        172800    IN    NS    ns2.google.com.

google.com.        172800    IN    NS    ns1.google.com.

google.com.        172800    IN    NS    ns3.google.com.

google.com.        172800    IN    NS    ns4.google.com.

CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A NS SOA RRSIG DNSKEY NSEC3PARAM

CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20200501044824 20200424033824 39844 com. ss+4rYfzkonN+jWtZMie5klKYKfxt56CTnHT1mWndz11i9jBETjlVW1Q RlRZMyuAOh9Zs656bKdIvWNWpe34q3m7TUWNA0G4cYb+SCgpU7CM25jR gd8nbHmBWl6SYY5ipeufqg0c3f3aEQZJSoCKwrOCc0aVP5huEenAkzRM 0iQayQcK5DYJjr1hN3+Sb52FpEEjq1+YMNtCCiVK13Ecdg==

S84BDVKNH5AGDSI7F5J0O3NPRHU0G7JQ.com. 86400 IN NSEC3 1 1 0 - S84CDVS9VPREADFD6KK7PDADH0M6IO8H NS DS RRSIG

S84BDVKNH5AGDSI7F5J0O3NPRHU0G7JQ.com. 86400 IN RRSIG NSEC3 8 2 86400 20200502044627 20200425033627 39844 com. j57Xg9fsDAGcaa1zScHEfPAtzYjsL/CoxrdRVLXHXkuQvl/4B2Ibrlaq gIvZTGu0A/dHk3a+Y6yCSgJkdecMT1pQTphGP2vgqEA9cnO7qPg9Cc6V PcY5AEk9Ix+DB8qqOqp9UZUwT1wdTiv/ompEs49sHieGS5u6+Eq33FNs WpkwDxQt1woeDeaT6y6TGsRUxXXXmfjUyclouu+1j3UIpA==

;; Received 836 bytes from 192.55.83.30#53(m.gtld-servers.net) in 156 ms





google.com.        300    IN    A    172.217.24.142

;; Received 55 bytes from 216.239.38.10#53(ns4.google.com) in 153 ms

 

4. dig <도메인> +short

바쁜 현대인을 위한 응답코드만 출력

 

[root@kbseo-test1 stlapp]# dig google.com +short

172.217.25.206

 

 

'System > Linux' 카테고리의 다른 글

사용자 계정 생성  (0) 2020.03.11

안녕하세요! 

지난시간에 AWS의 간단한 용어에 대해 설명을 해 드렸는데요

이번에는 AWS 구성에 가장 기본이 되는 VPC를 구성해 보도록 하겠습니다.

 

지난시간 이야기

[AWS] - AWS 기초시리즈 #1 - AWS 시작시 알아야 하는 용어

[AWS] - AWS 기초시리즈 #2 - AWS 가입, 계정 설정하기

[AWS] - AWS 기초시리즈 #3 - AWS IAM 계정생성

 

테라폼을 이용하여 VPC를 구축한다면 요기

[IaC/Teraform on AWS] - [Terraform on AWS] #1 - Terraform을 이용해 AWS 인프라환경을 구축 / VPC 생성

 

 

 

먼저 VPC를 구성하기전에 VPC가 무엇인지 알아야겠죠

 

VPC (Amazon Virtual Private Cloud)는 AWS 계정전용 가상 네트워크인데요,

조금 쉽게 말해 AWS에서 사용하는 네트워크를 격리하는 개념입니다.

일종의 VPC를 이용하여 하나의 AWS계정에서 멀티테넌트로 여러 서비스를 분리하실 수 있습니다!

 

 

 

VPC구성순서

1. VPC 구성 

2. VPC 내부의 subnets 구성

3. 인터넷게이트웨이 생성

4. NAT 게이트 웨이 생성

5. 라우팅테이블 설정

 


 

아래의 어키텍처처럼  보통 서비스의 가용성을 높이기 위하여 2개의 존으로 분리하여 구성을 해줍니다.

이 하나의 존을 Availability Zone이라 부르며 줄여서 AZ라고 부릅니다!

 

 

 

지금은 굉장히 복잡해 보이실수 있지만 차근차근 하나씩 구성을 해보면서 더 익혀보도록 하죠

 

1. VPC 구성

 

AWS 내부의 리소스에서 사용할 네트워크을 구분짓기 위하여 VPC를 먼저 구성을 해줄텐데요

추가적으로 VPC는 리전에 종속되기에 다른 리전에 나누어서 같은 서비스를 연결하고자 하실때에는 각각 리전별로 다른 VPC를 구성 후 VPC Peering을 통해 연결해주어야 합니다.

 

VPC에서 사용하는 사설 아이피 대역은 아래와같습니다.

- 10.0.0.0 ~ 10.255.255.255(10/8 prefix)

- 172.16.0.0 ~ 172.31.255.255(182.16/12 prefix)

- 192.168.0.0 ~ 192.168.255.255(192.168/16 prefix)

 

일단 만들어 봅시다.

 

1) aws 콘솔에 로그인을 한 후 서비스메뉴에서 VPC를 클릭하여 줍니다.

 

2) VPC 대시보드에서 Your VPCs를 클릭 후 Create VPC를 눌러줍니다.

 

 

3) 생성할 VPC의 이름과 CIDR 블록을 지정해줍니다.

aws default vpc CIDR은 172.31.0.0/16 입니다.

 

10.100.0.0/16 대역으로 VPC를 구성해 주었으며

한번 구성된 네트워크 대역대는 변경이 불가하므로 넉넉하게 잡아주시는거를 추천드립니다.

 

 

 

 

 

2. Subnet 구성

 

 

서브넷은 보통 처음 아키텍쳐의 Availability Zone 내부의 네트워크개념인데요

보통 하나의 AZ안에 Public subnet, Private subnet 이렇게 2개의 서브넷으로 구성해줍니다.

 

 

 

구성을 할때 이건 퍼블릭용, 이건 프라이빗용 나누어서 구성을 하진않고

서브넷중에서 인터넷게이트웨이와 연결될(외부에서 접속할 수 있는) 서브넷을 public subnet이라고 하며

인터넷접근할 필요없는 내부 리소스들을 묶어줄 서브넷을 Private subnet이라고 합니다. 

 

Public subnet

  • 인터넷 트래픽이 가능합니다.

  • Public IP를 통해 외부에서 접근이 가능합니다.

  • 인터넷 게이트웨이가 연결될 서브넷입니다.

Private subnet

  • 인터넷연결이 불가능합니다.

  • 외부 트래픽이 필요 할 경우 Public subnet에 있는 NAT게이트웨이로 트래픽을 보내 외부와 통신합니다.

 

먼저 구성을 해 봅시다!

 

(먼저 구성하시기 전에 어떠한 대역대를 사용할 것인지 정해두면 구성을 좀 더 수월하게 진행하실 수 있습니다.)

보통 운영환경에서는 가용성을 높이기 위하여 Multi AZ로 구성을 하기때문에 AZ별로 2개의 서브넷(퍼블릭, 프라이빗) 

한국리전에 3개의 AZ가 있기때문에 6개의 서브넷을 구성하기도 합니다.

 

(나중되면 어떤 대역대가 어떤 서브넷인지 구분하기 어려워...지기도.....)

 

 

 

AZ1

AZ2

AZ3

Public subnet

10.100.10.0/24

10.100.20.0/24

10.100.30.0/24

Private subnet

10.100.11.0/24

10.100.21.0/24

10.100.31.0/24

 

저는 보통 위에 도표와 같이 제가 구분하기 쉽게 퍼블릭 서브넷을 10단위로 맞춰서 구성하고

프라이빗 서브넷은 홀수의 IP대역으로 구성해줍니다.

 

하지만 저는 테스트용도이기에

AZ 1개로 구성을 진행하겠습니다 ^0^

 

1) VPC 대시보드에서 subnet 클릭

 

 

2) 생성할 서브넷의 이름과 좀전에 생성하였던 VPC, AZ, 그리고 서브넷 CIDR블록을 지정하여줍니다.

저는 AZ1존에 public subnet을 먼저 생성하였습니다.

 

서브넷 생성과정을 반복합니다.

AZ를 하나 사용할 경우 2개의 서브넷 (Public, Private)을 생성하시면 됩니다!

 

 

 

 

 

3. Internet Gateway 구성

 

 

VPC에 종속되며, 인터넷에 연결하기 위하여 생성하는 게이트웨이입니다.

보통 public subnet에있는 내부 IP주소를 외부 IP로 매핑해주는 NAT같은 역할을 합니다.

 

1) VPC대시보드에서 Internet Gateways 항목을 누른후 Create internet gateway를 클릭하여줍니다.

 

 

 

2) 이름을 지정해준 후 생성해줍니다.

 

 

3) 처음에 생성하였던 VPC에 attach해줍니다.

 

 

 

4. NAT Gateway 구성

 

Private subnet에 연결된 서버들이 인터넷에 연결될 수 있도록 만들어주는 게이트웨이입니다.

 

 

1) VPC대시보드에서 NAT Gateways 항목을 누른후 Create NAT Gateway를 클릭하여줍니다.

 

 

 

2) NAT G/W가 위치될 서브넷을 지정후 IP를 할당해줍니다.

  • Subnet :  좀전에 생성하였던 public subnet을 선택해줍니다.

    • NAT가 Public zone에 위치하고 있어야 private 대역대에 있는 리소스들을 NAT를 통하여 외부로 연결할 수 있습니다.

  • EIP : 기존에 할당된 EIP가 있으시면 선택해주시고, 없다면 오른쪽에 Allocate Elastic IP address를 선택해 EIP를 생성해줍니다.

  • Tag : 저는 NAT의 이름을 함께 tag로 지정해주었습니다.

 

현재까지 구성한 것을 도식화 하여보면 아래와 같습니다!

(subnet은 AZ1존에 각각 하나씩 구성하였습니다.)

 

 

 

5. Routing Table구성

 

실제 트래픽을 게이트웨이들로 보내주려면 라우팅테이블을 구성해줘야합니다.

(저는 subnet별로 룰을 다르게 지정해줄거기에 public subnet용 라우트테이블, private subnet용 라우트테이블 2개를 구성하겠습니다.)

 

1) VPC대시보드에서 Route Tables 항목을 누른후 Create route table을 클릭하여줍니다.

 

 

 

 

2) Route Table의 이름과 VPC를 지정해줍니다.

1,2번을 반복하여 private subnet용 라우트테이블로 생성해줍니다.

 

3) 생성한 Route table에 rule을 지정해줍니다.

  • Public subnet

    • Destination : 0.0.0.0/0 

    • Target : Internet Gateway

 

  • Private subnet

    • Destination : 0.0.0.0/0 

    • Target : NAT Gateway

 

4) 생성한 Route table에 Subnet을 연결해줍니다.

public route table에는 public subnet을, private table에는 private subnet을 연결

 

  • Public route table

 

 

 

프라이빗 테이블에도 마찬가지로 해당 작업을 반복해줍니다.

 

 

이렇게 해서 아래와 같은 VPC구성을 마쳤습니다!

 

 

 

환경을 구성할때 네트워크 망을 구축하는것이 가장먼저 해야할 일이기에

VPC구성은 가장 중요한 구성 중 한가지이며

숙지하는데 도움이 되였기를 바랍니다 ㅎ.ㅎ

 

다음시간에는

가장 많이 들어보았던 EC2 구성을 해볼꼐욤!

 

 

 

 

 

 

참고

https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/what-is-amazon-vpc.html

 

# 참고
https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/what-is-amazon-vpc.html

 

 

쿠버네티스를 들어는봤는데... 컨테이너를 관리하는거라고 알고는 있는데...

정확히 이 녀석이 무엇을 하는건지 이해가 잘 안가는 분들을 위한

Kubernetes 기초개념!

[Container, Kubernetes] - [Container 시리즈] 00. Container란? Docker란? - 컨테이너, 도커 개념

[Container, Kubernetes] - [Container 시리즈] 01. 도커를 설치하고 실행해보자! Docker on Amazon Linux

[Container, Kubernetes] - [Container 시리즈] 02. Docker사용법 Docker Basic Command

[Container, Kubernetes] - [Container 시리즈] 03. Docker File, Docker Image - 도커파일 및 이미지에 대하여

[Container, Kubernetes] - [Container 시리즈] 04. Application을 컨테이너화 해보자

 

안녕하세요! 

지난시간에 Container와 Docker에 대한 글을 작성하였었는데 

Kubernetes가 과연 무엇인지? 

왜 컨테이너를 이야기하면 쿠버네티스가 나오는지? 

그럼 컨테이너와 쿠버네티스가 같은것인지? 

이번시간에 자세히 다뤄보도록 하겠습니다!

 

지난글에서 설명드린 Container와 Docker가 기억나시나요?

예를들어 여러분이 새롭게 오픈한 신규 서비스가 있다고 가정해보겠습니다.

개발자들이 열씸히 코드를 개발하여 요즘 핫하디 핫한 컨테이너화 하게 구축을 한 후 서버에 이 컨테이너를 배포를 하였습니다.

 

대망의 오픈 첫날! 사용자가 신규 서비스로 접속을 하기 시작합니다.

가장 떨리는 순간이죠

 

하지만? 너무나 핫한 신규서비스이기에 저희가 예측했던 사용자보다 훨씬 더 많은 사용자가 몰리기 시작하네요...

즐거운 비명입니다.

 

음... 사용자가 몰리니...

scale out을 해야할 시점인 것 같습니다.

서버의 확장? 자신있습니다!

클라우드 환경이라면 더더욱 간단하죠

 

서버를 확장하였어요!!!

근데 잠시만....

저희 신규서비스는 컨테이너 환경인데......

안에있는 컨테이너들은..... 어떻게 옮겨야하지....?

 

 

여차저차해서 새롭게 확장한 서버에 컨테이너를 가져왔습니다!!

하지만.....

이렇게 가져온 컨테이너를 어떻게 적절하게 배치를 해야하는걸까요......

이렇게해서

다수의 컨테이너를 관리해주는

Container Orchestration 이라는 개념이 나오게 되었습니다!

 

즉,

오케스트레이션 이란 단어를 들으면 다음의 이미지를 떠올리신 분들이 계시리라 생각되는데

 

출처 : KBS 교향악단

 

 

저희 컨테이너 환경에서의 오케스트레이션은

다음의 이미지라 생각하시면 조금 쉬우실 것 같습니다!

쿠버네티스도 이러한 컨테이너 오케스트레이션 중 하나의 툴인데 

쿠버네티스 뿐만아니라, Docker Swarm, Rancher, Apache Mesos 등등 여러가지 툴이 존재하고 있습니다.

 

 

그중에서 이번 글에서는 대표적인, De facto(사실상 업계표준) Kubernetes에 대하여 알아보겠습니다!!

 

 

 

Kubernetes란?

Kubernetes

쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다.

쿠버네티스는 선언적 구성과 자동화를 모두 용이하게 해준다. 쿠버네티스는 크고, 빠르게 성장하는 생태계를 가지고 있다.

쿠버네티스 서비스, 기술 지원 및 도구는 어디서나 쉽게 이용할 수 있다.

쿠버네티스란 명칭은 키잡이(helmsman)나 파일럿을 뜻하는 그리스어에서 유래했다.

구글이 2014년에 쿠버네티스 프로젝트를 오픈소스화했다.

쿠버네티스는 프로덕션 워크로드를 대규모로 운영하는 15년 이상의 구글 경험과 커뮤니티의 최고의 아이디어와 적용 사례가 결합되어 있다.

라고 kubernetes의 공식 문서에 나와있습니다 ㅎ_ㅎ

즉 쿠버네티스는 앞에서 설명드린대로 컨테이너를 관리를 위해 나온 오픈소스 플랫폼입니다! (갓구글이 만듬)

쿠버네티스 특징이라고 하면 굉장히 많은 정보들이 쏟아져 나오는데요 대표적으로 아래의 3가지 특징이 있습니다.

 

 

1. 확장성

Google에서 만든것의 명성에 걸맞게 일주일에 수십억 개의 컨테이너들을 운영하게 해준 경험에 따라 쿠버네티스가 디자인되었기 때문에, 손쉽게 확장될 수 있습니다.

2. 유연성

로컬 테스트, 프로덕트 운영이든 환경에 상관없이, 사용자의 복잡한 니즈를 모두 수용할 수 있는 유연성을 가지기에 사용자의 애플리케이션들을 끊임없고 쉽게 전달할 수 있습니다.

3. 이식성

쿠버네티스는 오픈소스로서 on-prem, 하이브리드, 또는 퍼블릭 클라우드 인프라스트럭처등 여러 환경에서 기동됩니다.

그 밖에 수 많은 장점, 특징을 가지고 있는 쿠버네티스 이지만 굉장히 단순한 로직을 가지고있습니다.

현재상태를 모니터링하면서 관리자가 설정한 상태의 값과 다르면, 관리자가 설정한값으로 바꿔주는 3단계의 심플한 법칙

그렇기에 관리자는 명령어로 관리하는것이 아니라, 설정한 값이 들어있는 yaml 파일등으로 관리를 해 줍니다.

 

Kubernetes workflow

쿠버네티스는 다음과 같은 흐름을 가지고 있습니다.

 

보통은 조직마다 다르겠지만 협업사 혹은 협업부서에서 서비스에 해당하는 요청을 관리자 에게 전달합니다.

관리자는 이 명렁을 Master Node에 전달하고

Master Node는 Worker Node에게 명령어를 전달함과 동시에 트래픽을 분배해줍니다.

위와같은 다이어그램을 조금 더 자세히 살펴보자면

 

위와 같은 아키텍처가 나옵니다!

기본적으로 쿠버네티스는 하나의 마스터노드와 여러개의 워커노드로 구성이 되어져있는데

굉장히 복잡하고 뭐가 내부에 있는지 궁금하지도, 알고싶지도 않게 생겼지만

해당 아키텍처에 있는 Kubernetes의 컴포넌트에 대해서 하나하나 간략하게 살펴보겠습니다  ^0^(해맑)

Kubernetes Components

Master Node

: 쿠버네티스의 주요 컨트롤 유닛으로서 Worker Nodes를 관리하는 주체입니다.

클러스터에 관한 전반적인 결정을 하고 이벤트를 감지, 반응하는 역할을 합니다

Component

설명

Kubectl

-마스터 노드와 통신하는 명령어로서 쿠버네티스 API를 사용해서 마스터노드와 상호작용을 합니다.

API Server

- REST API 요청을 처리하고 쿠버네티스 클러스터를 구성하는 각 컴포넌트들과 통신을 담당합니다.

Scheduler

- 노드들의 리소스 상태를 파악하여 pod가 배치될 적절한 노드를 선택해 주는 역할.

Controller Manager

- 쿠버네티스 클러스터 상태 감시, 설정한 상태로 유지하는 역할.

ETCD

- 오픈소스 key-value 저장소로서 Kubernetes에서는 Master Node의 API Server가 HTTP/JSON API를 이용하여 접근할 수 있는 구성 데이터를 저장하는 용도로 사용됩니다.

 

Worker Node

: 워커노드는 할당된 task를 요청대로 수행하는 시스템입니다.

예전에는 Minions 라고도 불렸으며 컨테이너들간의 네트워크 등 서비스에 필요한 전반적인 일들을 마스터 노드와 통신하며 수행합니다.

Component

설명

Kubelet

- 쿠버네티스 마스터 노드간의 통신을 담당하는 에이전트로서 노드에서 동작하는 pod들을 관리합니다

Kube-proxy

- 각 노드별로 탑재되며 네트워크 프록시 및 로드밸런서 역할을 해줍니다.

Pod

- Pod는 컨테이너의 그룹으로 한 개 또는 여러 개의 컨테이너를 포함하는 쿠버네티스의 작업단위 입니다.

 

각각의 컴포넌트들이 굉장히 복잡해 보이는데 조금 더 쉬운 다이어그램을 가지고 왔습니다.

 

Kuberenetes 도큐먼트에 한번쯤 들어가보셨다면 익숙하실 그림일겁니다.

 

 

조금더 쉽게 말씀드리자면,

마스터노드는 쿠버네티스 클러스터를 관리하며

워커노드는 실질적인 업무를 수행하는 주체입니다. 열일하는 worker node 친근하네요

 

또한 이 워커노드를 확대하면 오른쪽 다이어그램처럼 되는데요,

워커노드안에는 pod가 들어가게 되고

pod안에는 containerized된 application이 들어가게됩니다!

이 pod는 쿠버네티스의 가장작은 작업단위 요소로서,

필요에 따라 쉽게 생성되고 쉽게 버려지는 비교적 짧은 수명을 가지는 것이 특징입니다.

또한, 각각의 pod마다 다른 ip를 가지고 있고 pod 안에 있는 컨테이너끼리 는 내부 통신이 가능합니다.

(DNS로 통신 (coredns))

Pod안에 있는 컨테이너들 끼리 볼륨을 공유하며

컨테이너가 죽고 재시작 되어도 pod가 살아있는 한 shared volume은 유지됩니다.

여러분의 Application을 컨테이너로 이쁘게 만들고 이를 사용자들에게 서비스를 하려면

실질적으로 동일한 pod가 지속적으로 올라와져 있어야하는데요~

(좀 전에 pod는 쉽게 죽는 특징을 가지고 있다고 했는데 ....)

우리의 쿠버네티스는 똑똑한 친구이니 이런 빅픽쳐를 계산해두었습니다.

 

 

어디에서 많이들어본...

Replica Set, Deployment, Service, Ingress 등등

모임에서 한번 쯤 들었던거같은 이름들..

다음시간에는 이런 Kubernetes의 구성요소들에 대하여 더 깊게 알아보는 시간을 가지도록 하겠습니다!

뜬금없지만 다들 코로나 조심하세요!

 

 

 

 

 

 

 

참고 URL

Container Orchestration Image : https://www.awsforbusiness.com/what-is-container-orchestration/

 

 

 
AWS에서 기본적으로 제공하는 모니터링 서비스인 Cloudwatch룰 이용하면 Memory, Disk 사용량을 보지 못하는 제한이 있기에
Custom metric을 이용하여서 상세 모니터링 필요
 
작업 정보
- Amazon Linux AMI를 이용
- 모니터링할 서버에 접속 후 진행
 
 
작업순서
  1. Packge 설치
  2. 모니터링 스트립트 다운
  3. AWS Credential 입력
  4. Cron 일정을 걸어 Cloudwatch에 주기적으로 지표전송
  5. Cron 재시작
 

 
1. Packge 설치
 
sudo yum install -y perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https perl-Digest-SHA.x86_64
 
 
2. 모니터링 스트립트 다운
curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O
 
unzip CloudWatchMonitoringScripts-1.2.2.zip && \
rm CloudWatchMonitoringScripts-1.2.2.zip && \
cd aws-scripts-mon
 
 
3. AWS Credential 입력
cp awscreds.template awscreds.conf
 
3-1 )  awscreds.conf 파일 수정
AWSAccessKeyId= <my-access-key-id>
AWSSecretKey= <my-secret-access-key>
 
# 해당 access key와 secret key는 IAM 항목에서 발급 / 확인 가능합니다.
 
 
 
4. Cron 일정을 걸어 Cloudwatch에 주기적으로 지표전송
 
4-1 )  Crontab 편집
crontab -e
 
4-2)  5분마다 메모리 및 디스크 공간 사용량을 CloudWatch에 전송
*/5 * * * * /home/aws-scripts-mon/mon-put-instance-data.pl --mem-used-incl-cache-buff --mem-avail --mem-util --swap-util
--disk-path=/ --disk-space-util --disk-space-avail --disk-space-used --from-cron
 
 
5. Cron 재시작
$ sudo service crond restart
Stopping crond:                                            [  OK  ]
Starting crond:                                            [  OK  ]
 
 
> AWS Console창에서 확인 했을 시 
사용자 지정 네임스페이스 항목에 새롭게 추가된 지표들을 확인 할 수 있습니다.
 


 


 
 
> Cron에 등록하지 않고 메모리 지표를 수집하고 CloudWatch로 보내려면
./mon-put-instance-data.pl --mem-used-incl-cache-buff --mem-util --mem-used --mem-avail

추가적으로 Custom Metric 지표 옵션
> Custom Metric 지표 옵션
이름
설명
--aggregated[=only]
인스턴스 유형, AMI ID 및 리전 전체에 대한 집계 측정치를 추가합니다. =only 값은 선택 사항입니다. 이 값을 지정하면 스크립트는 집계된 메트릭만 보고합니다.
--auto-scaling[=only]
Auto Scaling 그룹에 대해 집계된 측정치를 추가합니다. =only 값은 선택 사항입니다. 이 값을 지정하면 스크립트는 Auto Scaling 메트릭만 보고합니다. 스크립트를 사용하여 IAM 계정 또는 역할과 연결된 IAM 정책에는 EC2 작업 DescribeTags를 호출할 권한이 있어야 합니다.
--aws-access-key-id=VALUE
호출자를 식별하는 데 사용할 AWS 액세스 키 ID를 지정합니다. --aws-secret-key 옵션과 함께 사용해야 합니다. 이 옵션은 --aws-credential-file 매개 변수와 함께 사용하지 마십시오.
--aws-credential- file=PATH
AWS 자격 증명이 들어 있는 파일의 위치를 제공합니다.
이 매개 변수는 --aws-access-key-id 및 --aws-secret-key 매개 변수와 함께 사용할 수 없습니다.
--aws-iam-role=VALUE
AWS 자격 증명을 제공하는 데 사용되는 IAM 역할을 지정합니다. =VALUE 값이 필요합니다. 자격 증명을 지정하지 않으면 EC2 인스턴스와 연결된 기본 IAM 역할이 적용됩니다. IAM 역할은 하나만 사용할 수 있습니다. IAM 역할이 없거나 IAM 역할이 두 개 이상 있는 경우 스크립트에서는 오류를 반환합니다.
이 옵션은 --aws-credential-file--aws-access-key-id 또는 --aws-secret-key 매개 변수와 함께 사용하지 마십시오.
--aws-secret-key=VALUE
CloudWatch에 대한 요청에 서명하는 데 사용할 AWS 보안 액세스 키를 지정합니다. --aws-access-key-id 옵션과 함께 사용해야 합니다. 이 옵션은 --aws-credential-file 매개 변수와 함께 사용하지 마십시오.
--disk-path=PATH
보고할 디스크를 선택합니다.
PATH는 보고해야 할 파일 시스템의 마운트 지점 또는 마운트 지점에 있는 모든 파일을 지정할 수 있습니다. 디스크를 여러 개 선택하는 경우 각 디스크에 대해 --disk-path=PATH를 지정합니다.
/ 및 /home에 마운트된 파일 시스템의 디스크를 선택하려면 다음 매개 변수를 사용하십시오.
--disk-path=/ --disk-path=/home
--disk-space-avail
선택한 디스크의 DiskSpaceAvailable 측정치를 수집하여 전송합니다. 이 측정치는 GB 단위로 보고됩니다.
Linux 운영 체제의 예약된 디스크 공간으로 인해 사용된 디스크 공간 및 사용 가능한 디스크 공간이 총 디스크 공간에 정확하게 더해지지 않을 수 있습니다.
--disk-space-units=UNITS
디스크 공간 사용량을 보고할 단위를 지정합니다. 단위를 지정하지 않으면 디스크 공간은 GB 단위로 보고됩니다. UNITS는 바이트, KB, MB, GB 중 하나입니다.
--disk-space-used
선택한 디스크의 DiskSpaceUsed 측정치를 수집하여 전송합니다. 기본적으로 이 측정치는 GB 단위로 보고됩니다.
Linux 운영 체제의 예약된 디스크 공간으로 인해 사용된 디스크 공간 및 사용 가능한 디스크 공간이 총 디스크 공간에 정확하게 더해지지 않을 수 있습니다.
--disk-space-util
선택한 디스크의 DiskSpaceUtilization 측정치를 수집하여 전송합니다. 이 측정치는 % 단위로 보고됩니다.
참고로, 이 스크립트로 계산되는 디스크 사용률 측정치는 df -k -l 명령으로 계산한 값과 다릅니다. df -k -l 명령으로 계산한 값이 더 유용하다고 생각하면 스크립트에서 계산 값을 변경할 수 있습니다.
--from-cron
Cron에서 스크립트를 호출하는 경우 이 옵션을 사용합니다. 이 옵션을 사용하면 모든 진단 결과가 표시되지 않지만 사용자 계정의 로컬 시스템 로그에 오류 메시지가 전송됩니다.
--help
사용 정보를 표시합니다.
--mem-avail
MemoryAvailable 측정치를 수집하여 전송합니다. 이때, MB 단위로 보고합니다. 이 지표는 애플리케이션 및 운영 체제에서 할당한 메모리만 사용량으로 계산하며, --mem-used-incl-cache-buff 옵션을 지정하는 경우 캐시 및 버퍼 메모리도 사용량에 포함시킵니다.
--mem-used
MemoryUsed 측정치를 수집하여 전송합니다. 이때, MB 단위로 보고합니다. 이 지표는 애플리케이션 및 운영 체제에서 할당한 메모리만 사용량으로 계산하며, --mem-used-incl-cache-buff 옵션을 지정하는 경우 캐시 및 버퍼 메모리도 사용량에 포함시킵니다.
--mem-used-incl-cache-buff
이 옵션을 추가하면 --mem-util--mem-used 및 --mem-avail의 지표를 보고할 때 현재 캐시 및 버퍼용으로 사용 중인 메모리가 "사용됨"으로 표시됩니다.
--mem-util
MemoryUtilization 측정치를 수집하여 % 단위로 보고합니다. 이 지표는 애플리케이션 및 운영 체제에서 할당한 메모리만 사용량으로 계산하며, --mem-used-incl-cache-buff 옵션을 지정하는 경우 캐시 및 버퍼 메모리도 사용량에 포함시킵니다.
--memory-units=UNITS
메모리 사용량을 보고할 단위를 지정합니다. 단위를 지정하지 않으면 메모리는 MB 단위로 보고됩니다. UNITS는 바이트, KB, MB, GB 중 하나입니다.
--swap-used
SwapUsed 측정치를 수집하여 전송합니다. 이때, MB 단위로 보고합니다.
--swap-util
SwapUtilization 측정치를 수집하여 전송합니다. 이때, % 단위로 보고합니다.
--verbose
스크립트가 수행한 작업에 대한 자세한 정보를 표시합니다.
--verify
측정치를 수집하는 스크립트 실행을 테스트하고, 전체 HTTP 요청을 준비하지만 데이터를 보고하기 위해 CloudWatch를 실제로 호출하지는 않습니다. 이 옵션 역시 자격 증명이 제공되었는지 확인합니다. 자세한 정보 표시 모드에서 실행 중인 경우 이 옵션은 CloudWatch에 전송될 측정치를 출력합니다.
--version
스크립트의 버전 번호를 표시합니다.
참고 URL
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/mon-scripts.html
 
 
  Lambda 함수와 CloudWatch를 이용하여 Daily 백업 및 삭제
 
- 추가사항
백업 대상
백업 주기
백업 시간
보관 주기
삭제 대상
삭제 주기
삭제 시간
기타
실행중인 EC2 Instances AMI, Volumes
매일
당일 새벽 5시
7일
생성 후 7일이 지난 AMI, Snapshots
매일
당일 새벽 6시
 
 
- 순서는 다음과 같습니다.
    1. IAM 설정
    2. Lambda 함수작성 및 테스트
    3. CloudWatch 설정

 

 
 

IAM 설정

: AMI와 볼륨의 Snapshot을 위하여 EC2 Access를 허용하는 정책을 설정하여 줍니다.
 
1. 서비스에서 IAM을 클릭후 대쉬보드로 들어간 뒤 [역할] , [역할 만들기]를 차례대로 클릭하여 줍니다.
 
 
 
 
 
2. Lambda를 이용하여 자동백업, 삭제를 시행할 것이기에 [Lambda]서비스를 클릭한 후 아래의 [다음]을 누릅니다.
 
3.  다음 페이지의 [정책생성] 버튼을 클릭, 그 후 JSON탭을 누르면 보이는 기존의 코드를 지운 후  다음과 같은 코드를 넣어줍니다.
 
# IAM Role 
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:*",
            "Resource": "*"
        }
    ]
}
 
 
4.  아래에 나오는 [정책검토] 버튼을 클릭한 후 설정값에 맞는 이름을 넣어 주고 아래의 [정책생성] 버튼을 클릭합니다.
 
5.  다시 처음의 IAM 대쉬보드에서 [역할], [역할만들기]를 재 클릭 해줍니다.
 
6.  정책에 만들어주었던 이름을 검색하여 선택한 후 아래의 [다음]버튼을 클릭합니다.
 
7. 역할 이름을 지정하여 줍니다. (태그 값은 지정하지 않고 넘어갔습니다.) 그 후 아래의 [역할 만들기] 버튼을 눌러줍니다.
 
 
8.  기존 검색창 리스트에 방금 만들어 논 역할이 보여지게 됩니다.
 
 
 
 

Lambda 함수 작성 및 테스트

: 사전에 실행 중 이던 EC2 인스턴스에 태그를 지정해 주어서 태그 값이 지정된 인스턴스만 백업이 진행되도록 하였습니다.
(Key : tag-key , Value : Backup) 
 
 
1. 서비스의 Lambda 대쉬보드에 들어가 [함수생성] 버튼을 클릭하여 줍니다.
 
 
2.  이름을 지정 한 후 처음에 지정해주었던 IAM역할을 선택해 줍니다. 그 후 [함수생성] 버튼을 클릭합니다.
: Python 2.7 이용
 
 
3.  기존의 Default코드를 삭제한 후 다음과 같은 코드를 넣고 아래의 기본설정 제한시간을 1분으로 조정해 줍니다.
 
# Automated AMI Backups
#
# @author Robert Kozora <bobby@kozora.me>
#
# This script will search for all instances having a tag with "Backup" or "backup"
# on it. As soon as we have the instances list, we loop through each instance
# and create an AMI of it. Also, it will look for a "Retention" tag key which
# will be used as a retention policy number in days. If there is no tag with
# that name, it will use a 7 days default value for each AMI.
#
# After creating the AMI it creates a "DeleteOn" tag on the AMI indicating when
# it will be deleted using the Retention value and another Lambda function
import boto3
import collections
import datetime
import sys
import pprint
ec = boto3.client('ec2',region_name='ap-northeast-2')
#image = ec.Image('id')
def lambda_handler(event, context):
     
    reservations = ec.describe_instances(
        Filters=[
            {'Name': 'tag-key', 'Values': ['backup', 'Backup']},
        ]
    ).get(
        'Reservations', []
    )
    instances = sum(
        [
            [i for i in r['Instances']]
            for r in reservations
        ], [])
    print "Found %d instances that need backing up" % len(instances)
    to_tag = collections.defaultdict(list)
    for instance in instances:
        try:
            retention_days = [
                int(t.get('Value')) for t in instance['Tags']
                if t['Key'] == 'Retention'][0]
        except IndexError:
            retention_days = 7
        #for dev in instance['BlockDeviceMappings']:
        #    if dev.get('Ebs', None) is None:
        #        continue
        #    vol_id = dev['Ebs']['VolumeId']
        #    print "Found EBS volume %s on instance %s" % (
        #        vol_id, instance['InstanceId'])
            #snap = ec.create_snapshot(
            #    VolumeId=vol_id,
            #)
             
            #create_image(instance_id, name, description=None, no_reboot=False, block_device_mapping=None, dry_run=False)
            # DryRun, InstanceId, Name, Description, NoReboot, BlockDeviceMappings
            create_time = datetime.datetime.now()
            create_fmt = create_time.strftime('%Y-%m-%d')
         
            AMIid = ec.create_image(InstanceId=instance['InstanceId'], Name="Lambda - " + instance['InstanceId'] + " from " + create_fmt, Description="Lambda created AMI of instance " + instance['InstanceId'] + " from " + create_fmt, NoReboot=True, DryRun=False)
             
            pprint.pprint(instance)
            #sys.exit()
            #break
         
            #to_tag[retention_days].append(AMIid)
             
            to_tag[retention_days].append(AMIid['ImageId'])
             
            print "Retaining AMI %s of instance %s for %d days" % (
                AMIid['ImageId'],
                instance['InstanceId'],
                retention_days,
            )
    print to_tag.keys()
     
    for retention_days in to_tag.keys():
        delete_date = datetime.date.today() + datetime.timedelta(days=retention_days)
        delete_fmt = delete_date.strftime('%m-%d-%Y')
        print "Will delete %d AMIs on %s" % (len(to_tag[retention_days]), delete_fmt)
         
        #break
     
        ec.create_tags(
            Resources=to_tag[retention_days],
            Tags=[
                {'Key': 'DeleteOn', 'Value': delete_fmt},
            ]
        )
 
 
4.  상단에 [저장] 버튼을 누른 후 옆에 테스트 버튼을 눌러 테스트 파일을 만들고 테스트 버튼을 한번 더 눌러 실행시켜줍니다.
 
5.  EC2 대시보드로 가서 AMI와 볼륨의 Snapshot이 제대로 작동되는지 확인하여 줍니다
 
 

CloudWatch 설정

: 지정된 시간에 함수를 트리거 하기 위하여 CloudWatch를 이용합니다.
 
 
1.  서비스항목에서 CloudWatch를 클릭하여 옆 대시보드에 [규칙] , [규칙생성]을 차례대로 클릭하여 줍니다.
 
 
2.  지정된 시간에 함수를 시행할 것이므로 [일정]탭으로 들어 간 후 [Cron식]으로 매일 새벽 5시에 백업시간을 지정해 줍니다. 그 후 옆에 연결할 Lambda함수를 좀전에 작성하였던 Backup함수를 지정해 줍니다.
: Cron식은 GMT시간으로 계산되기때문에 한국시간에서 -9시간을 해주면 됩니다. 
 
Cron 식
00 20 ? * MON-SUN *
 
 
3.  아래에 [세부 정보 구성] 버튼을 클릭한 후 설정할 CloudWatch의 이름과 설명을 기술한 후 [규칙 생성] 버튼을 클릭합니다.
 
 
 
 
 

Scheduled Delete
 
주기적으로 삭제하는 방법도  Lambda함수코드와 Cron식만 달라지고 2,3번 항목에 대해선 동일한 방법으로 진행됩니다.
 
 
# Automated AMI and Snapshot Deletion
#
# @author Robert Kozora <bobby@kozora.me>
#
# This script will search for all instances having a tag with "Backup" or "backup"
# on it. As soon as we have the instances list, we loop through each instance
# and reference the AMIs of that instance. We check that the latest daily backup
# succeeded then we store every image that's reached its DeleteOn tag's date for
# deletion. We then loop through the AMIs, deregister them and remove all the
# snapshots associated with that AMI.
import boto3
import collections
import datetime
import time
import sys
ec = boto3.client('ec2', 'ap-northeast-2')
ec2 = boto3.resource('ec2', 'ap-northeast-2')
images = ec2.images.filter(Owners=["self"])
def lambda_handler(event, context):
    reservations = ec.describe_instances(
        Filters=[
            {'Name': 'tag-key', 'Values': ['backup', 'Backup']},
        ]
    ).get(
        'Reservations', []
    )
    instances = sum(
        [
            [i for i in r['Instances']]
            for r in reservations
        ], [])
    print "Found %d instances that need evaluated" % len(instances)
    to_tag = collections.defaultdict(list)
    date = datetime.datetime.now()
    date_fmt = date.strftime('%Y-%m-%d')
    imagesList = []
    # Set to true once we confirm we have a backup taken today
    backupSuccess = False
    # Loop through all of our instances with a tag named "Backup"
    for instance in instances:
    imagecount = 0
        # Loop through each image of our current instance
        for image in images:
            # Our other Lambda Function names its AMIs Lambda - i-instancenumber.
            # We now know these images are auto created
            if image.name.startswith('Lambda - ' + instance['InstanceId']):
                # print "FOUND IMAGE " + image.id + " FOR INSTANCE " + instance['InstanceId']
                # Count this image's occcurance
            imagecount = imagecount + 1
                try:
                    if image.tags is not None:
                        deletion_date = [
                            t.get('Value') for t in image.tags
                            if t['Key'] == 'DeleteOn'][0]
                        delete_date = time.strptime(deletion_date, "%m-%d-%Y")
                except IndexError:
                    deletion_date = False
                    delete_date = False
                today_time = datetime.datetime.now().strftime('%m-%d-%Y')
                # today_fmt = today_time.strftime('%m-%d-%Y')
                today_date = time.strptime(today_time, '%m-%d-%Y')
                # If image's DeleteOn date is less than or equal to today,
                # add this image to our list of images to process later
                if delete_date <= today_date:
                    imagesList.append(image.id)
                # Make sure we have an AMI from today and mark backupSuccess as true
                if image.name.endswith(date_fmt):
                    # Our latest backup from our other Lambda Function succeeded
                    backupSuccess = True
                    print "Latest backup from " + date_fmt + " was a success"
        print "instance " + instance['InstanceId'] + " has " + str(imagecount) + " AMIs"
    print "============="
    print "About to process the following AMIs:"
    print imagesList
    if backupSuccess == True:
        myAccount = boto3.client('sts').get_caller_identity()['Account']
        snapshots = ec.describe_snapshots(MaxResults=1000, OwnerIds=[myAccount])['Snapshots']
        # loop through list of image IDs
        for image in imagesList:
            print "deregistering image %s" % image
            amiResponse = ec.deregister_image(
                DryRun=False,
                ImageId=image,
            )
            for snapshot in snapshots:
                if snapshot['Description'].find(image) > 0:
                    snap = ec.delete_snapshot(SnapshotId=snapshot['SnapshotId'])
                    print "Deleting snapshot " + snapshot['SnapshotId']
                    print "-------------"
    else:
        print "No current backup found. Termination suspended."
 
CleanUp Cron 식
00 21 ? * MON-SUN *
 
 
 
Sample application으로 dockerized 하는 과정에 대해 기술
안녕하세요! 굉장히 오랜만에 블로그로 다시 찾아온 것 같습니다.

 

지난시간에 Docker의 기본적인 개념과 어떻게 동작했는지를 알아봤는데요,
이번에는 실질적으로 사용하고있는 Application을 어떻게 Containerized 할지에 관련된 주제를 가지고 돌아왔습니다.
 
순서는 다음과 같습니다.
1. Source code clone
2. npm build
3. docker file 생성
4. docker file을 통한 docker image 생성
5. docker run을 이용한 컨테이너 실행

1. Source Code Clone.

 

해당 Source 들은 GitLab에 올려져 있으며.
해당 애플리케이션 같은경우 Hostname과 현재 시간을 출력해주는 simple application입니다.
 
자 그럼 Giblab에 올려진 코드들을 가지고 와봅니다.
[root@kbseo-test1 stl]# git clone http://192.168.197.132/root/stlapp.git
Cloning into 'stlapp'...
Username for 'http://192.168.197.132': kbseo
remote: Enumerating objects: 131, done.
remote: Counting objects: 100% (131/131), done.
remote: Compressing objects: 100% (69/69), done.
remote: Total 217 (delta 70), reused 112 (delta 56), pack-reused 86
Receiving objects: 100% (217/217), 564.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (84/84), done.
 

 

소스들을 서버로 잘 데리고 왔습니다.
참고로 말씀드리자면 해당 Application은 React와 Spring Boot로 만들어졌고 maven을 통해 build하도록 되어져있습니다.
추가로 Maven내에 npm build가 가능하도록 한 상태여서 maven 명령을 통해서 빌드가 가능합니다.

2. npm build

[root@kbseo-test1 stlapp]# ./mvnw package
[INFO] Scanning for projects...
[INFO] 
[INFO] -------------------------< no.kantega:stlapp >--------------------------
[INFO] Building spring-and-react 0.1
[INFO] --------------------------------[ war ]---------------------------------
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:install-node-and-npm (install node and npm) @ stlapp ---
[INFO] Installing node version v6.17.1
[INFO] Unpacking /root/.m2/repository/com/github/eirslett/node/6.17.1/node-6.17.1-linux-x64.tar.gz into /root/stl/stlapp/target/node/tmp
[INFO] Copying node binary from /root/stl/stlapp/target/node/tmp/node-v6.17.1-linux-x64/bin/node to /root/stl/stlapp/target/node/node
[INFO] Installed node locally.
[INFO] Installing npm version 3.10.10
[INFO] Unpacking /root/.m2/repository/com/github/eirslett/npm/3.10.10/npm-3.10.10.tar.gz into /root/stl/stlapp/target/node/node_modules
.....
[INFO] --- spring-boot-maven-plugin:2.0.1.RELEASE:repackage (default) @ stlapp ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:22 min
[INFO] Finished at: 2020-04-24T18:30:05+09:00
[INFO] ------------------------------------------------------------------------
[root@kbseo-test1 stlapp]# 
 
 
빌드를 완료해주었습니다!

3. docker file 생성

이렇게 가지고 온 source를 컨테이너화 하기위하여 docker file을 먼저 생성해 줘야겠죠?
[root@kbseo-test1 stlapp]# vim Dockerfile
FROM tomcat:8.5.50-jdk8-openjdk

MAINTAINER kbseo@osci.kr

ENV TZ=Asia/Seoul
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime

RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY target/stlapp-0.1.war /usr/local/tomcat/webapps/ROOT.war

 

Simple application은 hostname과 time zone을 출력해주는 간단한 동작을 하는 애플리케이션 이기에
docker file안에 timezone을 설정해주고 tomcat상에서 동작될 war파일을 복사해줍니다.

4. docker file을 통한 docker image 생성

 

이전 글에서 설정해드린것과 같이 docker는 image로 배포를 하기 때문에
만들어두었던 docker file을 image화 해 줍니다.
# 현재 가지고있는 이미지가 있나 확인을 해줍니다
[root@kbseo-test1 stlapp]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@kbseo-test1 stlapp]# 
이미지가 한개도 없는것을 확인하실수 있습니다.
이미지 형태로 빌드를 해줍니다!
[root@kbseo-test1 stlapp]# docker build -t stlapp:1.0 .
Sending build context to Docker daemon 252.2 MB
Step 1/6 : FROM tomcat:8.5.50-jdk8-openjdk
Trying to pull repository docker.io/library/tomcat ... 
8.5.50-jdk8-openjdk: Pulling from docker.io/library/tomcat
dc65f448a2e2: Pull complete 
346ffb2b67d7: Pull complete 
dea4ecac934f: Pull complete 
8ac92ddf84b3: Pull complete 
d8ef64070a18: Pull complete 
6577248b0d6e: Pull complete 
576c0a3a6af9: Pull complete 
6e0159bd18db: Pull complete 
944191e51caa: Pull complete 
9ee6a5ca751e: Pull complete 
Digest: sha256:d53c2079ea67db92f6d7c39e9450f641610336016fdddef5392c5afd41518e5e
Status: Downloaded newer image for docker.io/tomcat:8.5.50-jdk8-openjdk
 ---> b56d8850aed5
Step 2/6 : MAINTAINER jacobbaek@osci.kr
 ---> Running in 148cd746d772
 ---> 3b0a94a52842
Removing intermediate container 148cd746d772
Step 3/6 : ENV TZ Asia/Seoul
 ---> Running in 7398ad9609a2
 ---> 706e8669d2d6
Removing intermediate container 7398ad9609a2
Step 4/6 : RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
 ---> Running in 1bcb6e658984

 ---> 453ac37a79dd
Removing intermediate container 1bcb6e658984
Step 5/6 : RUN rm -rf /usr/local/tomcat/webapps/ROOT
 ---> Running in f3c3bf4eb17b

 ---> 32f3bddc0334
Removing intermediate container f3c3bf4eb17b
Step 6/6 : COPY target/stlapp-0.1.war /usr/local/tomcat/webapps/ROOT.war
 ---> 3f24f0f7deaa
Removing intermediate container 134e07409a14
Successfully built 3f24f0f7deaa
 
docker build 같은경우 지난시간의 글에서 좀 더 자세히 확인 가능하십니다 ㅎ.ㅎ

 

명령어에 대해서 간단히 설명을 다시 드리자면,
$ docker build <옵션> <dockerfile 경로>
저는 태그를 지정해주기 위하여 -t옵션을 사용해주었습니다.
태그는 <저장소이름>/<이미지이름>:<태그> 형식입니다.
다시 이미지를 확인해보면 좀전에 build한 이미지가 올라온 것을 확인 하실 수 있습니다!
[root@kbseo-test1 stlapp]# docker images
REPOSITORY          TAG                   IMAGE ID            CREATED             SIZE
stlapp              1.0                   3f24f0f7deaa        3 minutes ago       545 MB
docker.io/tomcat    8.5.50-jdk8-openjdk   b56d8850aed5        2 months ago        529 MB
어라? 왜 두개의 이미지가 올라가져있을까요....? 분명히 도커 빌드는 한번만 실행했는데.. 도커파일을 다시 살펴볼까요?
FROM tomcat:8.5.50-jdk8-openjdk

 

첫줄에서 답이 나왔습니다!
FROM 을 통해 tomcat이미지를 먼저 받아서 그 위에 차례대로 레이어를 쌓아가면서 도커파일을 실행하기에
이미지가 두개가 만들어지게 됩니다.
  1. docker run을 이용한 컨테이너 실행
이제 Image를 만들었으니 실행해봅시다!
[root@kbseo-test1 stlapp]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@kbseo-test1 stlapp]#
아직까지 실행되고있는 컨테이너가 없네요
[root@kbseo-test1 stlapp]# docker run -d -p 8081:8080 --name=stlapp stlapp:1.0
fc16ba3e9f3f03ba22a2ca0b7eb12909a8311b555ef34bcf9b0f591537a76d2a

 

명령어에 대해 간단히 설명드리자면
$ docker run <옵션> <이미지이름, ID > <명령> <매개변수>
이렇게 구성되어있습니다.
docker run -d -p 8081:8080 --name=stlapp stlapp:1.0 이 명령어를 보자면
  • -d 데몬모드로 컨테이너를 실행하고,
  • -p 옵션을 이용하여 외부포트를 연결해줍니다 <호스트포트>:<컨테이너포트> -> 8080컨테이너 포트를 8081포트를 이용해 외부로 연결시킵니다.
  • --name 컨테이너 이름을 지정해줍니다. 여기에서는 stlapp이라는 이름을 달아주었습니다.
  • 실행시킬 컨테이너와 태그정보를 입력해줍니다.
결과를 한번 봐볼까요?
[root@kbseo-test1 stlapp]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
fc16ba3e9f3f        stlapp:1.0          "catalina.sh run"   11 minutes ago      Up 11 minutes       0.0.0.0:8081->8080/tcp   stlapp
[root@kbseo-test1 stlapp]# 
실행되고있는 컨테이너를 확인하실 수 있습니다.
브라우저를 통해 확인해볼까요?
 
 
 
컨테이너 이미지의 ID와 현재 시간이 잘 출력되는것을 보실 수 있습니다.

 

하지만 빨간색이라 눈이 너무나 아픈것같은 느낌적인 느낌입니다
그래서 검은색으로 바꾸고 재 배포를 해볼까요??
순서는 간단합니다!
  1. 실행되고 있는 컨테이너 중지
  2. 해당 컨테이너 삭제
  3. 소스수정
  4. 소스빌드, 컨테이너 빌드
  5. 컨테이너 실행

1. 실행되고 있는 컨테이너 중지

단칼에 중지시켜 줍니다.
[root@kbseo-test1 src]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
fc16ba3e9f3f        stlapp:1.0          "catalina.sh run"   29 minutes ago      Up 29 minutes       0.0.0.0:8081->8080/tcp   stlapp

 
[root@kbseo-test1 src]# docker kill stlapp
stlapp


[root@kbseo-test1 src]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
fc16ba3e9f3f        stlapp:1.0          "catalina.sh run"   29 minutes ago      Exited (137) 3 seconds ago                       stlapp

 

docker kill 명령어를 통해 중지시켜준 후
docker ps 를 통해 확인해보면 상태가 바뀐것을 보실 수 있습니다.
브라우저를 통해 접속해봐도 접속이 안되는것을 보실 수 있죠

2. 해당 컨테이너 삭제

프로세스를 삭제시켜 줍니다.
[root@kbseo-test1 src]# docker rm stlapp
stlapp

[root@kbseo-test1 src]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

3. 소스수정

css코드를 수정하여 색상을 변경해줍니다. 저는 블랙블랙으로 바꿨습니다.(TMI)

4. 소스빌드

소스를 수정했으니 재빌드를 해줘야겠죠?
[root@kbseo-test1 stlapp]# ./mvnw package
INFO] Scanning for projects...
[INFO] 
[INFO] -------------------------< no.kantega:stlapp >--------------------------
[INFO] Building spring-and-react 0.1
[INFO] --------------------------------[ war ]---------------------------------
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:install-node-and-npm (install node and npm) @ stlapp ---
[INFO] Node v6.17.1 is already installed.
[INFO] NPM 3.10.10 is already installed.
[INFO] 
[INFO] --- frontend-maven-plugin:1.6:npm (npm install) @ stlapp ---
[INFO] Running 'npm install' in /root/stl/stlapp/frontend
...
...
[INFO] --- spring-boot-maven-plugin:2.0.1.RELEASE:repackage (default) @ stlapp ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 43.467 s
[INFO] Finished at: 2020-04-27T20:10:43+09:00
[INFO] ------------------------------------------------------------------------
 
소스를 빌드했으니 도커를 빌드해봅시다!
[root@kbseo-test1 stlapp]# docker build -t stlapp .
Sending build context to Docker daemon 252.2 MB
Step 1/6 : FROM tomcat:8.5.50-jdk8-openjdk
 ---> b56d8850aed5
Step 2/6 : MAINTAINER jacobbaek@osci.kr
 ---> Using cache
 ---> 3b0a94a52842
Step 3/6 : ENV TZ Asia/Seoul
 ---> Using cache
 ---> 706e8669d2d6
Step 4/6 : RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
 ---> Using cache
 ---> 453ac37a79dd
Step 5/6 : RUN rm -rf /usr/local/tomcat/webapps/ROOT
 ---> Using cache
 ---> 32f3bddc0334
Step 6/6 : COPY target/stlapp-0.1.war /usr/local/tomcat/webapps/ROOT.war
 ---> Using cache
 ---> 3f24f0f7deaa
Successfully built 3f24f0f7deaa
 
이미지가 만들어졌는지 확인해볼까요?
[root@kbseo-test1 stlapp]# docker images
REPOSITORY          TAG                   IMAGE ID            CREATED             SIZE
stlapp              1.0                   3f24f0f7deaa        3 hours ago         545 MB
stlapp              latest                3f24f0f7deaa        3 hours ago         545 MB
docker.io/tomcat    8.5.50-jdk8-openjdk   b56d8850aed5        2 months ago        529 MB
하나의 이미지가 추가로 생성된 것을 보실 수 있습니다!

5. 컨테이너 실행

돌려봅니다
[root@kbseo-test1 stlapp]# docker run -d -p 8081:8080 --name=stlapp stlapp
5140e8332057ed23c4bf491a36d2d63fa0d09f0ffc4378073e145c2626075c30
잘 올라가져있는지 확인해볼까요?
[root@kbseo-test1 stlapp]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
dd58841261fa        stlapp              "catalina.sh run"   55 seconds ago      Up 55 seconds       0.0.0.0:8081->8080/tcp   stlapp
 
 
이제 깔끔한 BLACK 색상으로 바뀌었습니다.
이렇게 제 local환경에서 테스트한 컨테이너들에게 TAG를 지정하여서 버전관리도 할 수 있습니다.
[root@kbseo-test1 stlapp]# docker tag stlapp:latest 192.168.197.130:5000/stlapp_kb:1.2.0

[root@kbseo-test1 stlapp]# docker images
REPOSITORY                       TAG                   IMAGE ID            CREATED             SIZE
192.168.197.130:5000/stlapp_kb   1.2.0                 3e72ae5de27a        5 minutes ago       545 MB
stlapp                           latest                3e72ae5de27a        5 minutes ago       545 MB
docker.io/tomcat                 8.5.50-jdk8-openjdk   b56d8850aed5        2 months ago        529 MB
[root@kbseo-test1 stlapp]# 
테스트를 끝냈으니 registry에 올려줄 차례죠
[root@kbseo-test1 stlapp]# docker push 192.168.197.130:5000/stlapp_kb:1.2.0
The push refers to a repository [192.168.197.130:5000/stlapp_kb]
The push refers to a repository [192.168.197.130:5000/stlapp_kb]
Get https://192.168.197.130:5000/v1/_ping: http: server gave HTTP response to HTTPS client

 

어랏? 안돼네요?
이유는 바로 도커는 https 통신을 하기 때문입니다.

 

고로 저는 http 통신을 하기위해
docker에게 직접 친절히 사용하고자 하는 ip를 등록해주도록 하겠습니다.

docker insecure

 

여러가지의 방법이 있지만
저는 daemon.json 파일 안에 등록을 해주도록 하겠습니다.
(가장 간단해서 이방법으로 하였습니다 히힛)
  1. /etc/docker/daemon.json 수정
[root@kbseo-test1 stlapp]# cat /etc/docker/daemon.json 
{
"insecure-registries":["192.168.197.130:5000"]
}
사용할 registry 주소와 포트를 입력해줍니다.
  1. dpcker 데몬 재기동
[root@kbseo-test1 stlapp]# service docker restart
Redirecting to /bin/systemctl restart docker.service
  1. 레지스트리에 login
[root@kbseo-test1 stlapp]# docker login http://192.168.197.130:5000
Username: admin
Password: 
Login Succeeded
  1. 레지스트리에 push
[root@kbseo-test1 stlapp]# docker push 192.168.197.130:5000/stlapp_kb:1.2.0
The push refers to a repository [192.168.197.130:5000/stlapp_kb]
c20036844421: Pushed 
64bc7cab37ab: Pushed 
caeac141f483: Layer already exists 
5245df7d360d: Layer already exists 
78f5460c83b5: Layer already exists 
c601709dd5d2: Layer already exists 
72ce39f2b7f6: Layer already exists 
33783834b288: Layer already exists 
5c813a85f7f0: Layer already exists 
bdca38f94ff0: Layer already exists 
faac394a1ad3: Layer already exists 
ce8168f12337: Layer already exists 
1.2.0: digest: sha256:93e8b021981faed5cb1e5b22f4c0694f841afc1aa4502fff78d7edf9ffdb97cf size: 2840
[root@kbseo-test1 stlapp]#

 

 
 
짜잔! 등록이 되었습니다
이번시간에는 간단한 Application을 컨테이너화 하여 실행하는거 까지 함께 했는데요 
간단하다고 했지만 실질적으로 여러 작업이 들어갔었습니다 
그래서 다음시간에는 이를 좀 더 간단히 수행하기위해
젠킨스를 이용하여 작업을 해보도록 하겠습니다!
뿅!

+ Recent posts