설치는 위링크를 참조하고 grafana svc type 만 LoadBalancer 로 변경한다.
k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana LoadBalancer 172.20.237.228 af7fa7486f6eb4ad4a6bde897210f4a9-206885623.ap-northeast-2.elb.amazonaws.com 3000:32317/TCP 32m
그라파나의 서비스가 다만들어지면 URL로 접근이 가능하다.
패스워드는 admin / admin 이다.
로그인후 할일은 data source 를 지정하는것이다. 우리는 prometheus 를 이용할것이다.
사용하는 자원의 제한은 위와같다. istio-init(initcontainer) proxy(envoy) 가 추가된다.
kubectl label namespace default istio-injection=enabled
namespace/default labeled
kubectl get ns -L istio-injection
NAME STATUS AGE ISTIO-INJECTION
default Active 46m enabled
namespace 에 라벨을 붙이면 자동으로 그뒤론 NS 에 sidecar가 붙게된다.
k run nginx-istio --image=nginx --restart=Never
pod/nginx-istio created
k get pod
NAME READY STATUS RESTARTS AGE
nginx-istio 0/2 PodInitializing 0 4s
pod1 2/2 Running 0 5m11s
이제 sidecar를 본격적으로 확인해보자.
kubectl apply -f istio-1.10.4/samples/addons
아까 다운로드한 istio 에서 샘플로제공된 애드온을 설치한다. 위와같은 명령어를 치면 모든 애드온이 설치된다. 애드온내부에 있는 특정 애드온만도 설치가능하니 필요하면 특정 애드온만 설치해도 된다.
kiali.yaml 를 설치할때 kind 에 MonitoringDashboard 가 있어야 설치가 되는데 처음에 한꺼번에 다 배포를 하면 실패한다 그럼 그냥 쿨하게 명령어 한번더 입력해주자.
이제 애드온으로 접근하기위해선 애드온의 서비스를 퍼블릭하게 변경해줘야하는데, 나는 이전에는 yaml를 손수 수정했는데 이부분이 싱크빅하다.
k get svc -n istio-system grafana -o yaml | sed -e "s/type: ClusterIP/type: LoadBalancer/" | kubectl apply -f -
service/grafana configured
k get svc -n istio-system kiali -o yaml | sed -e "s/type: ClusterIP/type: LoadBalancer/" | kubectl apply -f -
service/kiali configured
k get svc -n istio-system tracing -o yaml | sed -e "s/type: ClusterIP/type: LoadBalancer/" | kubectl apply -f -
service/tracing configured
sed 로 수정해서 바로 적용한다. 와우..당연히 내가 못하는건 아닌데 관념의 차이로 인하여 이런 사용을 생각못했다. 다음엔 써먹어야지
k top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
nks-pool-1119-w-gzi 223m 5% 1265Mi 16%
nks-pool-1119-w-kvi 172m 4% 1540Mi 20%
k top pod
NAME CPU(cores) MEMORY(bytes)
php-fpm-nginx-deployment-6bc7b6df77-fbdx9 9m 138Mi
storage-nfs-client-provisioner-5b88c7c55-dvtlj 2m 8Mi
자원은 얼마안쓰지만..혹시나 사용량이 늘어날까봐 scale을 늘렸다.
k scale deployment php-fpm-nginx-deployment --replicas=3
deployment.apps/php-fpm-nginx-deployment scaled
그리고 pod 를 확인했는데...
k get pod
NAME READY STATUS RESTARTS AGE
php-fpm-nginx-deployment-6bc7b6df77-bpf2g 2/2 Running 0 19s
php-fpm-nginx-deployment-6bc7b6df77-fbdx9 2/2 Running 3 32h
php-fpm-nginx-deployment-6bc7b6df77-rfpb2 0/2 ContainerCreating 0 19s
storage-nfs-client-provisioner-5b88c7c55-dvtlj 1/1 Running 0 10h
생성단계에서 멈춘 pod 가 있었다. 상태를 확인해보니
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/php-fpm-nginx-deployment-6bc7b6df77-rfpb2 to nks-pool-1119-w-gzi
Normal Pulled 28s kubelet, nks-pool-1119-w-gzi Container image "linuxer-regi.kr.ncr.ntruss.com/php-fpm:12" already present on machine
Normal Created 28s kubelet, nks-pool-1119-w-gzi Created container php-fpm
Normal Started 28s kubelet, nks-pool-1119-w-gzi Started container php-fpm
Normal Pulled 28s kubelet, nks-pool-1119-w-gzi Container image "nginx:1.21" already present on machine
Normal Created 28s kubelet, nks-pool-1119-w-gzi Created container nginx
Normal Started 28s kubelet, nks-pool-1119-w-gzi Started container nginx
Warning FailedPostStartHook 28s kubelet, nks-pool-1119-w-gzi Exec lifecycle hook ([/bin/sh -c chmod 777 /run/php-fpm.sock]) for Container "nginx" in Pod "php-fpm-nginx-deployment-6bc7b6df77-rfpb2_default(6978da29-8045-49a0-9745-6be3cc48c364)" failed - error: command '/bin/sh -c chmod 777 /run/php-fpm.sock' exited with 1: chmod: cannot access '/run/php-fpm.sock': No such file or directory
Exec lifecycle hook ([/bin/sh -c chmod 777 /run/php-fpm.sock]) for Container "nginx" in Pod "php-fpm-nginx-deployment-6bc7b6df77-rfpb2_default(6978da29-8045-49a0-9745-6be3cc48c364)" failed - error: command '/bin/sh -c chmod 777 /run/php-fpm.sock' exited with 1: chmod: cannot access '/run/php-fpm.sock': No such file or directory
lifecycle hook 이 정상동작하지 않았다. 음...이벤트상으론 컨테이너가 생성전에 hook이 동작한건데 이건좀 확인해봐야겠다.
조금있다가 컨테이너가 자동으로 재시작되며 Runing 상태로 변경됬다.
k logs php-fpm-nginx-deployment-6bc7b6df77-rfpb2 -c nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?)
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/09/02 00:30:55 [notice] 1#1: using the "epoll" event method
2021/09/02 00:30:55 [notice] 1#1: nginx/1.21.1
2021/09/02 00:30:55 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/09/02 00:30:55 [notice] 1#1: OS: Linux 5.4.8-050408-generic
2021/09/02 00:30:55 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/09/02 00:30:55 [notice] 1#1: start worker processes
2021/09/02 00:30:55 [notice] 1#1: start worker process 22
2021/09/02 00:30:55 [notice] 1#1: start worker process 23
2021/09/02 00:30:55 [notice] 1#1: start worker process 24
2021/09/02 00:30:55 [notice] 1#1: start worker process 25
2020년 2월에 완성된 블로그의 구조이니..이걸 우려먹은지도 벌써 1년이 훌쩍넘어다는 이야기다. 블로그를 좀더 가볍고 편한구조로 변경하려고 고민했으나..나는 실패했다.ㅠㅠ
능력이나 뭐 그런 이야기가 아니라..게으름에 진거다. 게으름에 이기기 위해서 글을 시작했다.
목적은 K8S 에 새로 만들기고, K8S의 특성을 가져가고 싶었다.
제일먼저 작업한것은 Wordpess 의 근간이 되는 PHP 다.
PHP는 도커파일을 먼저 작성했다.
FROM php:7.4-fpm
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libpng-dev \
libzip-dev \
libicu-dev \
libzip4 \
&& pecl install xdebug \
&& docker-php-ext-install opcache \
&& docker-php-ext-enable xdebug \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install exif \
&& docker-php-ext-install zip \
&& docker-php-ext-install gd \
&& docker-php-ext-install intl \
&& docker-php-ext-install mysqli
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /srv/app
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN echo "date.timezone=Asia/Seoul" >> /usr/local/etc/php/php.ini
RUN sed -i --follow-symlinks 's|127.0.0.1:9000|/run/php-fpm.sock|g' /usr/local/etc/php-fpm.d/www.conf
RUN sed -i --follow-symlinks 's|short_open_tag = Off|short_open_tag = On|g' /usr/local/etc/php/php.ini
RUN sed -i --follow-symlinks 's|9000|/run/php-fpm.sock|g' /usr/local/etc/php-fpm.d/zz-docker.conf
CMD ["php-fpm"]
몇가지 수정사항이 있었는데 먼저 tcp socket를 사용하지 않고, unix socket을 사용했다. 흔하게 file socket이라고도 하는데 nginx <-> php-fpm 의 socket 통신의 속도가 상승한다. nginx와 php-fpm이 같은 서버내에 있을때 사용할수 있는 방법이다. 또 zz-docker.conf 는 php 이미지에서 ext를 설치할때 docker 패키지를 사용하면설치되는데 이 conf파일안에 unix 소켓을 사용할수 없도록 만드는 설정이 있다.
[global]
daemonize = no
[www]
listen = 9000
위설정이 바로 그 설정이다 listen = 9000 이 fix로 박히게 되는데 이걸 수정해주지 않으면 www.conf를 아무리 수정해도 unix socket을 사용할수 없다. 변경하고 빌드는 정상적으로 됬다.
빌드후 push는 NCP 의 Container Registry 서비스를 이용했다. docker login 할때 sub account 의 access key 와 secret key를 생성해서 사용했다.
첫번째로 nignx pod 와 php-fpm container의 unix socket 을 공유하는 부분이다. emptyDir: medium:Memory 로 지정하면 메모리를 emptydir 로 사용한다 원래 컨셉은 shm 을 hostpath로 이용하여 마운트해서 사용하려했는데 편리한 방법으로 지원해서 사용해봤다. 일반 디스크에 unix socket를 사용하는것보다 속도가 빠를것이라 예상한다 벤치를 돌려보기엔 너무 귀찮았다.
두번째로 lifecycle: postStart다. nginx 프로세스가 시작하면서 소켓을 생성하기에 권한부족으로 정상적으로 php-fpm과 통신이 되지 않았다. 그래서 lifecycle hook을 이용하여 컨테이너가 모두 생성된 이후에 cmd 를 실행하도록 설정하였다.
세번째로 여러개의 파드에서 같은 데이터를 써야하므로 고민을 했다. NFS-Server pod 를 생성하여 내부에서 NFS-Server를 이용한 데이터를 공유하느냐, 아니면 NAS서비스를 이용하여 NFS Client provisioner 를 이용할것인가. 고민은 금방 끝났다. 편한거 쓰자! NAS를 사용했다.
NAS 서비스를 확인하고,
#프로비저너 설치
helm --kubeconfig=$KUBE_CONFIG install storage stable/nfs-client-provisioner --set nfs.server=169.254.82.85 --set nfs.path=/n2638326_222222
#프로비저너 설치확인
k get pod storage-nfs-client-provisioner-5b88c7c55-dvtlj
NAME READY STATUS RESTARTS AGE
storage-nfs-client-provisioner-5b88c7c55-dvtlj 1/1 Running 0 33m
#nfs-pvc 설치
cat << EOF | k apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: nfs-client
EOF
볼륨까지 프로비저닝했다.
그리고 네번째 nginx-config 다 configmap 으로 만들어져서 /etc/nginx/conf.d/default.conf 경로에 subpath 로 파일로 마운트된다.
이렇게 하면 이제 private key, public key, root ca chain 해서 Certificate Manager에 인증서가 등록이 가능하다. 여기에 잘 등록하면,
이렇게 인증서를 등록할수 있다. 인증서의 발급기관은 R3로 뜬다.
이제 드디어 ingress 를 만들 준비가 되었다. ingress 를 만들기 위해 먼저 svc가 필요하다.
k expose deployment php-fpm-nginx-deployment --type=NodePort --port=80 --target-port=80 --name=php-fpm-nginx-deployment
k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
php-fpm-nginx-deployment-svc NodePort 198.19.196.141 <none> 80:30051/TCP 24h