설치는 위링크를 참조하고 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 를 이용할것이다.
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
selector 는 label을 기반으로 pod와 매핑되기때문에 IP가 우선이 되서는 안된다 생각했다. IP는 고정된 값이 아니므로. 그래서 label 을 사용하기로 생각했다.
[root@linuxer-bastion ~]# k get svc my-service1 -o=jsonpath='{..selector}'
map[app:my-nginx1]
[root@linuxer-bastion ~]# k get svc my-service1 -o=jsonpath='{..selector}' | sed 's/map//'
[app:my-nginx1]
[root@linuxer-bastion ~]# k get svc my-service1 -o=jsonpath='{..selector}' | sed 's/map//' | sed 's/:/=/'
[app=my-nginx1]
[root@linuxer-bastion ~]# k get svc my-service1 -o=jsonpath='{..selector}' | sed 's/map//' | sed 's/:/=/' | tr -s '[[:space:]]' ' '
app=my-nginx1
먼저 jsonpath를 이용하여 service의 selector를 찾는다 여기서 sed 명령어로 map[app:my-nginx1] 이라는 문자열을 두번 파이프라인하여 [app=my-nginx1]로 변환된다. json으로 출력한 문자열은 = -> : 으로 치환되어 표기된다. 그래서 변경해줘야 했다. 괄호를 벗겼다. 괄호를 벗은 값은 내가 처음부터 원했던 service - selector - label 이다. 이제 이값을 이용해서 pod 를 리스팅 하고 label를 보면 완성이다.
k get pod -l $(k get svc my-service1 -o=jsonpath='{..selector}' /| sed 's/map//' | sed 's/:/=/' | tr -s '[[:space:]]' ' ') --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx1-67f499d79c-g7vr7 1/1 Running 0 26h app=my-nginx1,pod-template-hash=67f499d79c
my-nginx1-67f499d79c-j4f9k 1/1 Running 0 26h app=my-nginx1,pod-template-hash=67f499d79c
my-nginx1-67f499d79c-mqxzs 1/1 Running 1 26h app=my-nginx1,pod-template-hash=67f499d79c
내가 작성한 스크립트는 폰트크기 15다
k get ep -o custom-columns=IP:.subsets[].addresses[].ip
IP
10.0.12.10
198.18.0.74
198.18.0.173
198.18.0.6
성주님께서 주신 IP 추출 팁
오랜만에 머리를 굴렸더니 재미있었다.
오늘도 같이 머리를 싸매서 고민을 해주신 봄님, iamai 님, 성주님께 감사를 드린다.
더좋은 아이디어나 생각이 있다면 얼른 결과를 공유해주시길 바란다!
즐거운 새벽되시라!
하고 누우려는데 성주님께서 주신 IP list 로 하나더 만들고 싶었다.
k get ep my-service1 -o custom-columns=IP:.subsets[].addresses[*].ip | tr "," "\n" | grep -v IP | grep -f - <(kubectl get po -o wide --show-labels)
my-nginx1-67f499d79c-g7vr7 1/1 Running 0 27h 198.18.0.74 nks-pool-1119-w-gzg <none> <none> app=my-nginx1,pod-template-hash=67f499d79c
my-nginx1-67f499d79c-j4f9k 1/1 Running 0 27h 198.18.2.250 nks-pool-1119-w-gzh <none> <none> app=my-nginx1,pod-template-hash=67f499d79c
my-nginx1-67f499d79c-mqxzs 1/1 Running 1 27h 198.18.1.208 nks-pool-1119-w-gzi <none> <none> app=my-nginx1,pod-template-hash=67f499d79c
ping -M do -s 1472 google.com
PING google.com (172.217.175.110) 1472(1500) bytes of data.
76 bytes from nrt20s21-in-f14.1e100.net (172.217.175.110): icmp_seq=1 ttl=114 (truncated)
76 bytes from nrt20s21-in-f14.1e100.net (172.217.175.110): icmp_seq=2 ttl=114 (truncated)
76 bytes from nrt20s21-in-f14.1e100.net (172.217.175.110): icmp_seq=3 ttl=114 (truncated)
1500에 맞춰서 google로 보내면 정상적으로 간다.
ping -M do -s 1473 google.com
PING google.com (172.217.175.110) 1473(1501) bytes of data.
^C
--- google.com ping statistics ---
45 packets transmitted, 0 received, 100% packet loss, time 43999ms
1501 은 가지 않는다.
대부분의 클라우드 내부의 이더넷은 점보프레임이 설정되어 있으며 9000이상이다.
ifconfig | grep -i MTU | grep eth
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 8950
외부망으론 1500까지만 전송됨을 확인하였으니 내부망에서 MTU를 확인한다.
ping -M do -s 8922 10.0.12.13
PING 10.0.12.13 (10.0.12.13) 8922(8950) bytes of data.
8930 bytes from 10.0.12.13: icmp_seq=1 ttl=64 time=0.491 ms
8930 bytes from 10.0.12.13: icmp_seq=2 ttl=64 time=0.431 ms
8930 bytes from 10.0.12.13: icmp_seq=3 ttl=64 time=0.483 ms
잘된다.
인터페이스에 지정된 MTU는 8950이다. ping에선 IP Header(20 Bytes) + ICMP Header(8 Bytes) 28 Bytes 를 뺀 숫자가 ICMP Data 크기이다. 그래서 Ping 로 MTU 테스트할땐 실제 MTU-28을 하여 테스트하면된다.