
Kubernetes하고 Ansible를 연동하는 방법에 대해서 정리해보자.
이전 포스트에서 Kubernetes를 Docker 데스크탑에 있는 미니큐브 방식으로 설치를 했었다.
호스트 PC에서 Docker 데스크탑을 통해 Kubernetes를 사용해서 몇 가지 테스트를 해보았다.
이번에 해볼 테스트는 도커 컨테이너로 운영되고 있는 Ansible을 가지고 Playbook 파일을 활용해 Kubernetes에 접속하여 몇 가지 테스트를 해보려고 한다.
Ansible에서 사용할 수 있는 타켓을 설정하기 위해 host 파일에 몇 가지 그룹을 지정할 수 있다.
여기에 windows 그룹(=Kebernetes 주소)을 host 파일에 만들어 놓고 호스트 PC의 ip 주소 즉, Kubernetes 주소를 적도록 한다.
이 작업이 정상적으로 성공하게 되면 나중에 Jenkins하고 연동을 할 때, Jenkins에서 Ansible에다가 어떤 명령을 전달한다.
그럼 Ansible에서 가지고 있었던 Playbook 파일을 가지고 원했던 Kubernetes 클러스터에다가 필요한 명령어를 실행할 수 있다.
Ansible에서 Kubernetes가 설치되어 있는 PC로 SSH 연결을 한 다음에 해당하는 서버에 접속했을 때 그리고 kubectl이라는 명령을 가지고 직접적인 스크립트 파일을 실행해 볼 수 있다는 이야기이다.

docker exec -it ansible-server bash
Ansible이 도커로 작동되고 있는 상태이기 때문에 docker-exec-it라는 옵션을 가지고 Ansible 서버에 접속을 할 것이다.
ssh 사용자_계정@호스트pc_ip주소
Ansible 서버에 접속 후 Kubernetes가 설치되어 있는 PC로 SSH 명령으로 접속을 해 볼 것이다.
정상적으로 패스워드 입력하고 접속이 되면 이제 Ansible에서 Kubernetes를 접속해서 사용가능한 상태가 된다.
mkdir k8s
cd k8s
vi hosts
[ansible-server]
localhost
[windows]
호스트pc ip주소
Ansible 서버에서 Kubernetes를 하나의 타겟으로 놓고 사용을 하기 위해서는 호스터 파일을 작성하는 게 필요하다고 말했다.
k8s 폴더를 만들고 거기에 hosts 파일을 만든 후 vi 에디터로 그룹과 ip주소를 적어준다.

다음에 Ansible 서버에서 Kubernetes로 접속을 하면서 패스워드를 매번 입력하게 되면 작업하는 데 불편함이 따른다.
ssh-keygen
그래서 포스트에서 작업했던 것처럼 ssh-keygen 이라는 명령을 이용해서 접속할 수 있는 키를 하나 생성한 다음에
ssh-copy-id 사용자_계정@호스트pc_ip주소
지금 생성되어진 이 킷값을 Kubernetes 서버에다가 전송을 해서 매번 모듈을 실행하거나 플레이북을 실행을 할 때 패스워드 없이 실행될 수 있도록 하겠다.
ansible -i ./k8s/hosts kubernetes -m ping
그리고 테스트를 위해 Ansible 서버에서 Kubernetes가 설치되어 있는 PC로 Ping이라는 모듈을 실행할 것이다.
실제 Ansible 서버는 Docker로 구동 중이고, Kubernetes는 Docker Desktop, 즉 호스트 pc에 설치되어 있지만 하나의 각각의 노드로 보고 Ansible 노드에서 Kubernetes 노드로 명령어를 전달을 해서 정상적으로 핑 작업이 되는지 확인을 해볼 것이다.

일반적으로 Kubernetes는 우측 그림과 같이 마스터와 워커노드로 구성되어 있다.
하지만 필자가 쓴 구성은 싱글노드로 되어 있는 미니큐브를 사용하고 있는 상태라는 것을 기억하고 있어야 한다.
Ansible에서 Playbook을 실행하기 위해 Kubernetes엔 이전 포스트에서 만든 deployment와 service 스크립트 파일을 가지고 있어야 한다.
Ansible은 Kubernetes의 스크립트를 실행하기 위한 Playbook 파일을 만든다.
Ansible의 Playbook 파일에는 적용하고자 하는 hosts의 범위와 작업하고자 하는 tasks의 이름을 적어 주고, 실제 명령어로 쓰는 kubectl apply, 다음에 실행하고자 하는 Kubernetes의 스크립트 파일명을 지정해준다.


결과를 보면 Ansible 플레이북 파일할 때, Playbook에서는 windows 그룹만을 대상으로 실행하겠다고 하였었다.
따라서 대상은 windows 그룹인 Kubernetes만 실행될 것이다.
그럼 Kubernetes에서 실행중인 목록을 확인하였을 때 Deployment와 Pod, Service가 실행중인 것을 확인할 수 있다.
이를 바탕으로 실습을 진행해보자.
** Ansible-server : 파랑색
** Kubernetes : 흰색

docker exe -it ansible-server bash
Ansible이 도커로 가동되고 있는 상태이기 때문에 docker-exec-it라는 옵션을 가지고 Ansible 서버에 접속한다.
윈도우에 ssh 접속을 하기 위해서는 OpenSSH 설치가 필수이다.
하단 링크로 들어가면 윈도우에서 OpenSSH를 시작하기 위한 과정들이 상세히 기술되어 있다.
필자도 위 매뉴얼을 보고 그대로 진행하였다.
내용은 다음과 같다.
첫 번째로 선행되어야 할 것은 필수 구성 요소 검사 이다
필수 조건은 다음과 같다.
Windows 10(빌드 1809) 이상을 실행하는 디바이스
PowerShell 5.1 이상.
기본 제공 관리자 그룹의 멤버인 계정
PowerShell을 꼭 관리자로 열어준다.


winver.exe
Windows 디바이스의 버전 세부 정보를 확인한다.
필자는 윈도우 10을 사용하므로 조건에 부합한다.

$PSVersionTable.PSVersion
주 버전이 5 이상이고 부 버전이 1 이상인지 확인한다.
이 또한 주버전이 5, 부버전이 1이므로 조건에 부합한다.

(New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
현재 사용자가 관리자 권한을 가지고 있는지 확인하는 스크립트이다.
True가 나오면 부합하고, False가 나오면 부합하지 않는 것이다.
필자는 True가 나왔으므로 현재 사용자가 관리자 권한을 가지고 있다.
두 번째, Windows용 OpenSSH를 설치하는 과정이다.
방법은 Gui 방식과 PowerShell(Cli) 방식이 있는데 후자를 선택하였다.

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
서버와 클라이언트 둘 다 아직 설치되지 않은 경우 명령에서 다음 출력을 반환한다.
Name : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
필자는 Client는 Installed가 나오고, Server는 NotPresent가 나왔다.
따라서 Server를 설치해야 한다.

Add-WindowsCapability -Online -Name OpenSSH.Server
0.0.1.0
해당 명령어를 입력하면 Operation Running 이라고 뜨며 현재 설치 중임을 알 수 있다.

설치가 완료되면
Path :
Online : True
RestartNeeded : False
출력을 반환한다.

Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
OpenSSH 서버 서비스(sshd)를 시작한다.
OpenSSH 서버 서비스가 Windows 시작 시 자동으로 실행되도록 설정한다.
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
방화벽 규칙이 구성되어 있는지 확인후 없다면 설정에 의해 자동으로 생성되어야 한다.
이렇게 Windows용 OpenSSH가 설치되면 Ansible에서 Kubernetes로 접속할 수 있는 상태가 된다.
참고로 K8s는 Kubernetes와 동일하다
8은 K와 s 사이의 문자 개수를 뜻한다.

ipconfig
Ansible 서버에서 Kubernetes로 ssh 접속을 위해 Kubernetes가 설치된 호스트 pc의 ip주소를 확인한다.
윈도우 PC이기 때문에 ipconfig 명령어로 ip주소를 확인할 수 있다.
무선 LAN 어댑터 WI-FI에 Ipv4 주소가 172.30.1.23 인 것을 확인할 수 있다.

ssh 사용자_계정@호스트pc_ip주소
{ 윈도우 pc의 사용자 계정명 + @ + 위에서 확인한 호스트pc의 주소 }로 SSH 접속을 해보자.
사용자 계정의 올바른 비밀번호를 입력하게 되면

정상적으로 호스트 PC(=K8s)로 접속이 되는 것을 확인할 수 있다.

exit
exit를 입력하면 K8s에서 Ansible로 이동하며 ssh 접속이 해제된다.
Ansible에서 K8s로 접근 가능할 수 있도록 hosts 파일을 만들자.

vi hosts
[ansible-server]
localhost
[windows]
172.30.1.23
K8s 폴더를 만들고, K8s 폴더로 이동 후 hosts 파일을 생성한다.
host라는 파일은 인벤토리 파일로서 Ansible 서버에서 접속하려고 하는 서버들의 주소를 적는 파일이다.
vi 에디터로 ansible-server 그룹에는 localshot, windows 그룹에는 Host pc의 주소를 적어 저장해주면 된다.

ansible -i /k8s/hosts windows -m ping
/k8s/hosts 인벤토리 파일에 정의된 Windows 호스트들에 ping 요청을 보내어 호스트의 연결 상태를 확인하는 작업을 수행하였으나 권한이 없다고 오류가 발생하며 UNREACHABLE이 떴다.
이유는 Ansible 서버에서 Kubernetes가 설치되어 있는 호스트 PC에 로그인을 하지 않았다.
즉, 패스워드로 입력하지 않은 상태이기 때문에 Access Denied가 뜬 것이다.
이 작업을 해결하기 위해서 기존에 만들었던 키 값을 Kubernetes 서버에 복사를 해준다.

ssh-copy-id kimmi@172.30.1.23
ssh-copy-id 명령은 SSH 키 기반 인증을 위해 원격 호스트에 공개 키를 복사하는 유틸리티이다.
구체적인 동작은 다음과 같다:
kimmi는 원격 호스트에서 사용할 사용자 계정 이름
172.30.1.23은 원격 호스트의 IP 주소(=Windows PC=Kubernetes)
이 명령을 실행하면 현재 시스템(=Ansible 서버)의 ~/.ssh/id_rsa.pub 파일에 저장된 공개 키를 원격 호스트(=Windows PC=Kubernetes)의 ~/.ssh/authorized_keys 파일에 추가한다.
원격 호스트(=Windows PC=Kubernetes)의 사용자 계정 비밀번호를 묻는다.
공개 키가 성공적으로 복사되면 이후부터는 비밀번호 없이 SSH 키 기반 인증으로 원격 호스트에 접속할 수 있다.

cd .ssh
type authorized_keys
notepad authorized_keys
윈도우 pc에서 ssh 폴더의 authorized_keys 파일의 내용을 확인해보니 Ansible 서버의 정보가 추가 되지 않고 ECHO가 설정되어 있습니다 라는 문구가 저장되어 있었다.
이와 같은 문제가 발생하는 이유를 찾아보니 리눅스 서버는 SSH를 통해서 ansible이 통신하는 반면에 Windows 서버에서는 winrm 이라는 리모트 매니져를 통해서 통신하기 때문이었다.
따라서 필자는 맥OS가 아니라 윈도우pc를 쓰고 있으므로 SSH 방식이 아닌 winrm를 가지고 통신을 하도록 설정하였다.

yum install python39
Ansible 서버에는 python이 설치 되어 있지 않았기 때문에 python 설치한다.

pip install pywinrm
python 설치 후 pywinrm을 설치한다.

vi hosts
[ansible-server]
localhost
[windows]
호스트pc_ip주소
[windows:vars]
ansible_password='administrator암호'
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
ansible_user=관리자계정(ex, administrator)
ansible_port=5986
Ansible 서버에서 /etc/ansible/hosts 파일에 위와 같이 windows 서버의 정보를 입력한다.
(user와 password는 Windows PC 로그인 할 때 사용하는 관리자 계정을 사용하면 된다.)

$url="https://github.com/AlbanAndrieu/ansible-windows/blob/master/files/ConfigureRemotingForAnsible.ps1"
$file="$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url,$file)
powershell.exe -ExecutionPolicy ByPass -File $file
Windows 서버에서 위 명령어를 Powershell(관리자 모드)에서 실행한다.

ansible -i ./k8s/hosts ansible-server -m ping
ansible -i ./k8s/hosts windows -m win_ping
다시 한 번 /k8s/hosts 인벤토리 파일에 정의된 호스트의 ansible-server 그룹에 ping 요청을 보내어 호스트의 연결 상태를 확인을 했을 때 SUCCESS가 뜬다.
windows 그룹에 ping 요청을 보내도 연결 상태 확인 시 SUCCESS가 뜨며 Ansible 서버와 윈도우 pc 간의 통신이 잘 되는 것을 확인할 수 있다.

vi k8s-cicd-deployment-playbook.yml
Kubernetes Script를 실행하기 위한 파일을 Ansible 서버에서 Playbook을 만들어 준다.
이름은 k8s-cicd-deployment-playbook.yml로 하였다.
vi 에디터에 들어가서 다음 내용을 저장해주었다.
- name: Create pods using deployment
hosts: windows
# become: true
# user: ubuntu
tasks:
- name: create a deployment
win_command: kubectl apply -f C:\Users\kimmi\cicd-devops-deployment.yml
name : Playbook 파일에 이름을 쓰고
hosts : 다음에 적용하고자 하는 호스트를 지정 한다.
가지고 있는 호스트 파일 중 windows라고 되어 있는 그룹에 적용을 시켰다.
tasks : 어떠한 작업을 할 것인지는 task를 적어 놨는데
name : 필자는 deployment를 생성하는 작업을 할 것이다.
command : deployment 실행하기 위해서 kubectl apply -f 다음에 필요로 하는 필요로 하는 yml 파일 이름(cicd-devops-deployment.yml)을 적어준다.
이 yml 파일은 Kubernetes에서 실행할 수 있는 스크립트 파일이 된다.

호스트 pc(=Kuburnetes)에서 이전 포스트에서 만든 cicd-devops-deployment.yml 파일 내용을 확인해본다.
Ansible 서버에서 Playbook을 실행하면 Kubernetes의 해당 스크립트가 실행될 것이다.

kubectl get all
kubectl delete deployment.app/cicd-deployment
kubectl delete service/cicd-service
kubectl get all
Kubernetes 클러스터 내의 모든 리소스 객체(Pod, Service, Deployment, ReplicaSet 등)를 조회하여 기존에 실행되었던 Deployment와 Service 등이 있다면 모두 삭제시켜 빈 상태로 만들어준다.

ansible-playbook -i ./k8s/hosts k8s-cicd-deployment-playbook.yml
Ansible 서버로 돌아와 k8s-cicd-deployment-playbook.yml 파일을 Playbook 실행을 하면 hosts의 windows 그룹의 호스트(=Kubernetes)에서 kubectl apply -f C:\Users\kimmi\cicd-devops-deployment.yml 명령어를 실행하게 된다.

kubectl get all
Kubernetes에 돌아가 명령어가 잘 실행되었는지 확인해보면 Deployment가 정상적으로 실행되어 Pod도 2개가 생긴 것을 확인할 수 있다.
스크립트 파일이 어떤 원리로 돌아가는지 알고 싶다면 하단 포스트를 참고하길 바란다.

vi k8s-cicd-deployment-service.yml
- name: create service for deployment
hosts: windows
# become: true
# user: ubuntu
tasks:
- name: create a service
win_command: kubectl apply -f C:\Users\kimmi\cicd-devops-service.yml
마찬가지 방법으로 서비스도 똑같이 플레이북 파일과 위 스크립트 파일을 갖고 실행해보자.

호스트 pc(=Kuburnetes)에서 이전 포스트에서 만든 cicd-devops-service.yml 파일 내용을 확인해본다.
동일하게 Ansible 서버에서 Playbook을 실행하면 Kubernetes의 해당 스크립트가 실행될 것이다.

kubectl get services
실행 전에 호스트 pc(=Kuburnetes)에 services가 실행 중인지 확인한 후, 있다면 비워주고 실행해야 한다.

이전과 동일하게 Ansible 서버로 돌아와 k8s-cicd-service-playbook.yml 파일을 Playbook 실행을 하면 hosts의 windows 그룹의 호스트(=Kubernetes)에서 kubectl apply -f C:\Users\kimmi\cicd-devops-service.yml 명령어를 실행하게 된다.

Kubernetes에 돌아가 명령어가 잘 실행되었는지 확인해보면 Servcies 정상적으로 실행되어 외부에서도 접속이 가능한 상태가 되었다.

localhost@32000/hello/world/
웹 페이지에서도 32000번 포트로 정상적으로 내용이 출력됨을 알 수 있다.
Jenkins에서 Ansible 서버를 이용해서 Kubernetes를 제어하는 방법에 대해서 살펴보자.
먼저 Kubernetes 서버를 ssh 서버로 등록시켜주는 작업을 해줘야 한다.

대시보드 -> Jekins 관리 -> Systems로 이동하여 하단에 내려가면 SSH 설정하는 메뉴가 있다.
추가를 누른 뒤 Name은 k8-server, Hostname은 호스트PC의 IP주소인 172.30.1.16를 적어주었고, Username은 사용자 계정명인 kimmi를 적어주었고, Remote Directory는 .를 적어 주었다.
사용자 PC에 맞게 IP주소와 Username을 적어줘야 한다.
하단에 고급을 누르면 Password를 입력할 수 있는 필드가 나오는데, 여기는 사용자 계정의 패스워드를 적어주면 된다.

설정이 끝났으면 우측 하단에 Test Configuration을 눌러 테스트가 정상적으로 되는지 확인해본 뒤 저장을 눌러준다.

첫 번째 Job은 Jenkins에서 Kubernetes에 직접 접속할 수 있는 잡을 하나 만들어 볼 것이다.
여기서는 Ansible이 쓰이지 않고, 단순히 Jenkins에서 Kubernetes로 접속 가능한지 테스트 해보는 작업이라 생각하면 된다.
이름은 My-K8s-Project라고 적어주었고, 밑으로 내려가 기존에 사용했던 Ansible 프로젝트를 복사하여 작업하기 위해 Copy from에는 My-Ansible-Project라고 적어주었다.

다른건 모두 똑같고, 빌드 후 조치로 내려가 ansible-server로 되어있던 것을 지우고 방금 설정한 k8-server를 선택해주었다.
git에서 가지고 왔던 코드를 war 파일로 패키징을 하고 다음에 warfile을 해당하는 kubernetes에 복사하는 작업은 현재는 필요 없지만, 나중 이후의 작업에서 ci-cd 파이프라인을 연결할 때 사용되므로 삭제하지 않고 그대로 두었다.
Exec command에는 Kubernetes에서 cicd-devops-deployment.yml파일을 실행할 수 있도록 kubectl apply -f C:\Users\kimmi\cicd-devops-deployment.yml을 적어주었다.

저장 후 지금 빌드를 눌러주고 콘솔 창을 확인해보면 SUCCESS가 뜨는 것을 확인할 수 있다.
정상적으로 빌드가 완료되었고 현재 Jenkins에서 Kubernetes로 다이렉트로 접속을 해서 cicd-devops-deployment.yml 파일을 실행이 완료되었다는 뜻이다.

kubectl get all
Kubernetes(=Windows PC)에서 실행중인 오브젝트를 확인해보면 Deployment 한개가 생성되었고, Pod도 스크립트에서 정의한대로 2개가 생성되었다.

두 번째 Job은 Jenkins에서 Ansible을 거쳐 Kubernetes에 접속할 수 있는 잡을 만들어 보자.
이름은 My-K8s-Project-using-Ansible라고 적어주었고, 첫 번째 Job이었던 My-K8s-Project를 복사하여 사용하기 위해 Copy from에 적어주었다.

여기서 주의할 점은 추후에 CD작업으로 쓰일 것이기에 Poll SCM은 체크해제 해주었다.
CD에 대한 설명을 밑에서 더 자세히 설명하겠다.

빌드 후 조치로 내려가 Name을 k8-server 대신 ansible-server를 선택해준다.
Exec command에는
ansible-playbook -i ./k8s/hosts k8s-cicd-deployment-playbook.yml;
ansible-playbook -i ./k8s/hosts k8s-cicd-service-playbook.yml
를 입력한 뒤 저장한다.
해당 명령어로 Ansible 서버에서 Playbook을 실행하여 Kubernetes Deployment와 Service 관련 스크립트가 실행될 것이다.

kubectl delete service/cicde-service
kubectl delete deployment.apps/cicde-deployment
kubectl get all
빌드 전에 Kubernetes에선 실행중인 오브젝트가 없도록 기존에 존재했던 service와 deployment를 삭제시켜준다.

지금 빌드를 눌러 빌드를 실행해주고 콘솔에 SUCCESS가 뜨면 Kubernetes에서 스크립트가 정상적으로 실행되었다는 뜻이다.
Kubernetes로 돌아가 kubectl get all로 실행중인 오브젝트를 확인해보면 deployment와 service, pod가 실행 중임을 알 수 있다.

localhost:32000/hello-world/
service가 정상 실행되므로 32000번 포트로 외부에서 접근도 가능하다.

Jenkins를 이용해서 전체 CI, CD 과정의 프로세스를 완성해보자.
CI 작업에서는 가지고 있는 코드를 GitHub와 같은 형상관리 솔루션에다가 업로드를 하면 변경된 최신 코드를 가지고 와서 환경에 맞춰서 빌드를 한다.
빌드를 한 다음에 필요에 따라서 단위 테스트를 할 것이다.
여기에 이상이 없다라고 하면 이제 이 내용을 가지고 패키지 파일을 만든다.
패키징을 한 다음에 만들어지는 결과를 운영하려고 하는 서버에 배포를 하게 된다.
여기까지를 CI(Continuous Integration)이라고 한다.
그래서 CI에서 해야 될 내용을 정리해 보면 다음과 같다.
git pull
// 최신 코드 갖고 온다.
create a docker image
// 최신 코드에 대한 빌드가 성공적으로 완료가 되면 이 내용을 바탕으로 해서 컨테이너 이미지로 생성한다.
push the image to the registry (https://hub.docker.com)
//로컬에 생성된 컨테이너 이미지를 도커 허브 사이트의 레지스트리에다가 업로드를 한다.
remove the image form the local
//로컬에서 만들어져 있는 이미지를 삭제해주는 작업으로 마무리
최신 코드를 가지고 빌드되어 있는 결과물이 이미지화 돼서 레지스트리에 등록이 되었을 것이다.
등록된 레지스트리의 값을 CD 작업에서는 설치하고자 하는 서버에서 이미지를 다운로드 받은 후 해당하는 파일을 가지고 Kubernetes에서 Pod 및 Service를 실행하고 사용자가 사용할 수 있는 상태로 만들어야 한다.
create a deployment (replicaset: 2)
// Kubernetes에서는 Deployment 객체를 이용해서 2개의 Pod를 실행
create a service
//외부에서 해당하는 Pod를 사용할 수 있도록 Service를 등록
왼쪽에 있는 CI부터 오른쪽에 있는 CD까지 하나의 연쇄적인 프로세스를 구축할 수 있도록 Jenkins를 설정해보자.

Ansible 서버에서 도커 이미지를 만들어 도커 허브에 올린 후 로컬에서 이미지를 삭제하는 작업을 이전 포스트에서 한 적이 있다.
[DevOps] Ansible을 활용한 Docker 및 Jenkins CI/CD 파이프라인 구축 (feat. Windows)
해당 파일명은 create-cicd-devops-image.yml 파일이었으며, 이 파일을 이용해 Ansible Playbook를 실행할 것이다.
위에서 말했듯이 해당 작업이 CI 과정이라고 볼 수 있다.

kubectl delete service/cicd-service
kubectl delete deployment.apps/cicd-deployment
kubectl get all
CD 작업을 하려면 기존에 만든 Deployment와 Service는 삭제해놓자.

Jenkins로 돌아와 새로운 Job을 만들어주자.
이름은 My-K8s-Project-for-CI, 이전에 마든 My-K8s-Project-using-Ansible Job을 복사하여 사용하자.

여기서는 Git에서 코드가 변경됨을 감지하면 바로바로 업데이트 될 수 있도록 변경된 코드가 있으면 Poll SCM이 1분마다 일어날 수 있도록 꼭 체크해두자.

하단에 내려가 빌드 후 조치에선 ansible-server 인 것은 동일하나 Exec command를 ansible-playbook -i /K8s-hosts create-cicd-devops-image.yml --limit ansible-server로 적어주어 도커 이미지에 대한 Playbook이 실행될 수 있도록 적어준다.
이때 적용 대상은 hosts파일의 ansible-server 그룹만(=자기 자신) 적용될 수 있도록 limit 옵션을 주었다.
kubernetes와 관계없이 Ansible 서버에서 결과 이미지 파일을 만들고, 만들어진 이미지 파일을 도커 허브에 push해서 올리겠다는 뜻이다.

Apply 후 지금 빌드를 눌러 콘솔을 확인해보면 SUCCESS가 떴다.
SUCCESS가 떴다면 자신의 도커 허브를 확인해보면 최근 시간으로 업데이트(혹은 생성) 되었다.
CI 작업이 정상적으로 끝났으니 CD 작업을 해보자.

지금 만들어져 있는 프로젝트의 하단으로 내려가 하단에 빌드 후 조치 추가라는 부분을 하나 더 클릭한다.
이번에 Build other projects를 선택한다.
Build other projects를 골랐다는 이야기는 빌드가 끝난 다음에 어떤 프로젝트를 더 추가적으로 연계할 것인지를 설정할 수 있는 부분이다.

앞서 만들었던 My-K8s-Project-using-Ansible을 클릭해준다.
현재 있는 프로젝트가 정상적으로 성공한 다음에 My-K8s-Project-using-Ansible를 실행해달라는 뜻이다.
즉, CI 와 CD가 연쇄적으로 실행이 되겠다는 의미이다.

지금 빌드를 눌러 실행하면 콘솔에 SUCCESS가 찍히고, Build History에 시간을 비교해보면 My-K8s-Project-using-CI가 일어나고 1분 뒤에 My-K8s-Project-using-Ansible가 바로 일어났다.
이번엔 로컬에서 소스코드를 변경하여 Git에 커밋하여 푸시하면 Git의 소스코드가 변경될 것이다. 그럼 빌드를 하지 않아도 자동으로 My-K8s-Project-using-CI가 실행될 것이고, 자동으로 My-K8s-Project-using-Ansible도 실행되어 CI-CD가 연쇄적으로 일어날 것이다.

vi k8s-cicd-deployment-playbook.yml
- name: Create pods using deployment
hosts: kubernetes
# become: true
# user: ubuntu
tasks:
- name: delete the previous deployment
command: kubectl delete deployment.apps/cicd-deployment
- name: create a deployment
command: kubectl apply -f cicd-devops-deployment.yml
소스코드를 변경하기 전에 항상 Kubernetes의 Deployment를 직접 삭제하고 스크립트를 다시 실행하며 테스트를 진행했었는데 이 작업도 수동으로 하지 않도 자동으로 하기 위해 스크립트에 기존에 만들려는 deployment가 존재하면 삭제하고 스크립트를 실행할 수 있도록 변경하였다.
해당 작업은 필수가 아니며, 만약 에러가 발생한다 하더라도 무시하고 바로 스크립트가 실행될 수 있도록 변경하였다.

kubectl get all
기존에 만든 deployment의 시간을 잘 살펴보길 바란다.
CI-CD가 일어나면 deploymnet를 삭제하고 다시 만들기 때문에 최근 시간으로 변경될 것이다.


git add .
git commit -m "changed the index jsp file"
git push
소스코드를 변경한 후 커밋 후 푸시하여 Git에 소스코드를 변경하였다.

그럼 자동으로 CI-CD가 일어나며 My-K8s-Project-using-CI가 먼저 실행된 후 My-K8s-Project-using-Ansible가 바로 실행된다.

kubectl get all
CD가 완료될 때까지 수시로 kubectl로 확인하였다.
Pod의 STATUS를 확인해보면 종료되고 다시 만들어지는 것을 확인할 수 있다.

Service도 계속 실행 중이므로 외부에서도 32000번으로 접근 가능하다.