클러스터 안에 있는 jenkins pod에서 플러그인을 설치할려 했더니 다음과 같은 에러가 발생하였습니다
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
Caused: sun.security.validator.ValidatorException: PKIX path building failed
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341)
Caused: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
아니 회사의 프록시 환경도 아닌데 왜 이런 에러가 나지? 해서 원인을 분석했더니
self signed certificate 라고 잡히네요.
# curl https://google.com -v
* Trying 12.34.56.78:443...
* Connected to google.com (12.34.56.78) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
회사와 같이 프록시와 사내 인증서가 적용된 환경이 아닌데 왜 이런 현상이 발생하는지 계속 분석해보니
어떨때는 또 통신이 되기도 합니다.
그래서 무슨 차이인가 하여 traceroute를 시도해봤습니다.
정상적인 상황에서는 아래와 같이 통신을 하지만
# traceroute google.com
traceroute to google.com (172.217.25.174), 30 hops max, 60 byte packets
1 12-34-56-78.etcd.kube-system.svc.cluster.local (12.34.56.78) 0.689 ms 0.579 ms 0.541 ms
2 12.34.56.78 (12.34.56.78) 2.570 ms 2.532 ms 2.502 ms
3 * * *
4 100.82.171.49 (100.82.171.49) 1.135 ms 100.82.171.45 (100.82.171.45) 0.883 ms 0.844 ms
5 10.67.252.254 (10.67.252.254) 1.199 ms 10.67.252.250 (10.67.252.250) 4.219 ms 10.67.252.254 (10.67.252.254) 1.131 ms
6 10.222.35.212 (10.222.35.212) 2.253 ms 10.222.22.240 (10.222.22.240) 2.288 ms 10.222.18.160 (10.222.18.160) 1.949 ms
7 10.222.8.175 (10.222.8.175) 4.351 ms 10.222.20.25 (10.222.20.25) 6.528 ms 10.222.23.203 (10.222.23.203) 2.034 ms
8 72.14.203.90 (72.14.203.90) 30.108 ms 142.250.163.48 (142.250.163.48) 29.981 ms
72.14.216.72 (72.14.216.72) 36.144 ms
9 * * *
10 108.170.242.193 (108.170.242.193) 32.943 ms 108.170.242.129 (108.170.242.129) 35.381 ms 142.250.208.146 (142.250.208.146) 39.221 ms11 108.170.242.146 (108.170.242.146) 32.762 ms 108.170.242.209 (108.170.242.209) 39.643 ms 108.170.242.208 (108.170.242.208) 34.475 ms
12 209.85.246.213 (209.85.246.213) 36.130 msc 216.239.43.157 (216.239.43.157) 34.211 ms 209.85.241.107 (209.85.241.107) 34.799 ms
13 142.250.229.250 (142.250.229.250) 34.535 ms 37.353 ms sin01s16-in-f14.1e100.net (172.217.25.174) 29.530 ms
해당 yaml 파일은 namespace가 이미 지정되어 있기 때문에 (ingress-nginx)
그냥 바로 apply하면 된다.
kubectl apply -f ingress-nginx.yaml
------------------------------------------------------------------------
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
이제 ingress-nginx의 NodePort를 알아두자
kubectl get svc -n ingress-nginx
------------------------------------------------------------------------
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.105.81.137 <none> 80:31039/TCP,443:31171/TCP 60s
ingress-nginx-controller-admission ClusterIP 10.100.14.244 <none> 443/TCP 59s
31039 포트이니 접속 테스트를 해본다 (master node에서 테스트)
curl http://127.0.0.1:31039
------------------------------------------------------------------------
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
기본적으로는 MasterNode에서는 실제적인 Docker 컨테이너를 제공하지 않는다. (설정을 한다면 Master Node도 컨테이너 사용 가능)
애초에 VM의 환경인 만큼 Master Node는 단순 Master 역할에만 집중하게 하고
이 Node에 연결할 Slave 구성을 다음과 같이 진행했다.
# Master와 과정이 동일하다. 보기 편하게 하기 위해 내용을 복붙함.
# 기존 설치된 docker가 없으면 아래 명령어는 생략해도 됨
sudo apt-get remove docker docker-engine docker.io containerd runc
# ubuntu package 최신 정보 받아오기
sudo apt-get update
# docker 설치를 위한 기본 패키지 설치
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# apt로 내려 받을 수 있게 docker registry 설정
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# docker 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# docker 명령어를 편하게 사용하기 위해 sudo 권한 부여 (shell 재시작 필요)
sudo usermod -aG docker $USER
# 설치하기전 환경 구성
sudo swapoff -a
sudo sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
# kubernetes registry 등록
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# kubernetes 설치
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
# master node 설정시 아래의 내용을 잘 기록 해놨다면 다행이지만..
sudo kubeadm join 123.456.678.910:6443 --token nt4zj2.vbtcn33333t19zpzv \
--discovery-token-ca-cert-hash sha256:0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# 혹시 기록이 안되어 있다면? 걱정할 필요가 없다. 아래 명령을 수행하면 나온다.
# 각각 token과 hash 값을 확인할 수 있는 명령어이다.
kubeadm token list
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
# 만약 token list가 없다면? 걱정하지 말자 다시 만들면 된다
kubeadm token create
# 그리고 다시 hash를 조회하면 된다
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
- VM인 만큼 Snapshot을 통한 OS 백업이 간편하여 Master 노드를 안정적으로 운영
- Persistent Volume을 NAS로 구성을 하여 데이터의 안정성을 확보
- Synology를 게이트웨이 역할을 하게 수행하여 서비스에 대한 외부 접근시 보안성을 강화
위와 같은 이유로 아래와 같은 설정으로 Kubernetes 환경을 구성하였다.
VM의 구성 사양가상 디스크의 크기
기본 네트워크 사용
Ubuntu 20.04.03 server 버전 설치 후 다음의 패키지 설치
sudo apt install ssh
sudo apt install net-tools
Docker는 최신버전으로 설치
# 기존 설치된 docker가 없으면 아래 명령어는 생략해도 됨
sudo apt-get remove docker docker-engine docker.io containerd runc
# ubuntu package 최신 정보 받아오기
sudo apt-get update
# docker 설치를 위한 기본 패키지 설치
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# apt로 내려 받을 수 있게 docker registry 설정
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# docker 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# docker 명령어를 편하게 사용하기 위해 sudo 권한 부여 (shell 재시작 필요)
sudo usermod -aG docker $USER
Kubernetes 설치
# 설치하기전 환경 구성
sudo swapoff -a
sudo sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
# kubernetes registry 등록
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# kubernetes 설치
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Kubernetes Master 설정전 확인 사항
# cgroup driver 확인하기
sudo docker info | grep -i cgroup
# 만약 cgroup driver가 cgroupfs이면 다음 명령어 수행하여 해당 문구 수정
sudo vi /usr/lib/systemd/system/docker.service
# <Before>
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# vi 편집 후 systemctl 초기화 수행
sudo systemctl daemon-reload
sudo systemctl restart docker
Master Node 설정하기
# master node 초기화하기 (시간이 좀 걸림)
sudo kubeadm init
# 만약 설정 도중 꼬인게 있다면 초기화 하는 명령은 다음과 같다
sudo kubeadm reset
# 정상적으로 수행되면 아래의 문구를 만나야 한다.
Your Kubernetes control-plane has initialized successfully!
# 일반 유저로 다음의 명령어를 수행한다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 정상적으로 설정되었는지 확인하기 위해 master 노드의 상태를 조회한다.
kubectl get node
----------------------------------------------------------------------
NAME STATUS ROLES AGE VERSION
devopsmaster NotReady control-plane,master 4m17s v1.23.5
----------------------------------------------------------------------
여기까지 Synology의 VM을 위한 Kubernetes Master Node 구성이 모두 끝났다.
지금까지 깔끔한 구성을 하였으니 이 VM에 대한 스냅샷을 설정한다. (이건 귀찮으면 안해도 된다)
Synology Virtual Machine Manager에서 스냅샷 촬영 선택스냅샷 저장 (설명을 넣고 잠금을 체크하자)촬영된 스냅샷
A Splunksearchretrieves indexed data and can perform transforming and reporting operations. Results from one search can be "piped" (i.e., transferred) from command to command, to filter, modify, reorder, and group your results.
table / view
search results
Search resultscan be thought of as a database view, a dynamically generated table of rows, with columns.
index
index
All values and fields are indexed in Splunk, so there is no need to manually add, update, drop, or even think about indexing columns. Everything can be quickly retrieved automatically.
row
result / event
Aresultin Splunk is a list of field (i.e., column) values, corresponding to a table row. Aneventis a result that has a timestamp and raw text. Typically in event is a record from a log file, such as: 173.26.34.223 - - [01/Jul/2009:12:05:27 -0700] "GET /trade/app?action=logout HTTP/1.1" 200 2953
column
field
Fieldsin Splunk are dynamically returned from a search, meaning that onesearchmight return a set of fields, while another search might return another set. After teaching Splunk how to extract out more fields from the raw underlying data, the same search will return more fields that it previously did. Fields in Splunk are not tied to a datatype.
database / schema
index / app
In Splunk, anindexis a collection of data, somewhat like a database has a collection of tables. Domain knowledge of that data, how to extract it, what reports to run, etc, are stored in a Splunkapp.
SELECT * FROM mytable WHERE (mycolumn1="true" OR mycolumn2="red") AND mycolumn3="blue"
source=mytable AND (mycolumn1="true" OR mycolumn2="red") AND mycolumn3="blue"
AS (alias)
SELECT mycolumn AS column_alias FROM mytable
source=mytable |RENAMEmycolumn as column_alias |FIELDScolumn_alias
BETWEEN
SELECT * FROM mytable WHERE mycolumn BETWEEN 1 AND 5
source=mytable mycolumn<=1 mycolumn>=5
GROUP BY
SELECT mycolumn, avg(mycolumn) FROM mytable WHERE mycolumn=value GROUP BY mycolumn
source=mytable mycolumn=value |STATSavg(mycolumn) BY mycolumn |FIELDSmycolumn, avg(mycolumn)
HAVING
SELECT mycolumn, avg(mycolumn) FROM mytable WHERE mycolumn=value GROUP BY mycolumn HAVING avg(mycolumn)=value
source=mytable mycolumn=value |STATSavg(mycolumn) BY mycolumn |SEARCHavg(mycolumn)=value |FIELDSmycolumn, avg(mycolumn)
LIKE
SELECT * FROM mytable WHERE mycolumn LIKE "%some text%"
source=mytable mycolumn="*some text*"
Note:The most common search usage in Splunk is actually something that is nearly impossible in SQL -- to search all fields for a substring. The following search will return all rows that contain "some text" anywhere.
Note:COLLECT is typically used to store expensively calculated fields back into Splunk so that future access is much faster. This current example is atypical but shown for comparison with SQL's command. source will be renamed orig_source
UPDATE mytable SET column1=value, column2=value,... WHERE some_column=some_value
Note:There are a few things to think about when updating records in Splunk. First, you can just add the new values into Splunk (see INSERT INTO) and not worry about deleting the old values, because Splunk always returns the most recent results first. Second, on retrieval, you can always de-duplicate the results to ensure only the latest values are used (see SELECT DISTINCT). Finally, you can actually delete the old records (see DELETE).
<Bluetooth Settings> FN + Space: Bluetooth On/Off FN + Z: Long Press: First Bluetooth Equipment Pair Short Press: Connect/Disconnect to First Bluetooth Equipment FN + X: Long Press: Second Bluetooth Equipment Pair Short Press: Connect/Disconnect to Second Bluetooth Equipment FN + C: Long Press: Third Bluetooth Equipment Pair Short Press: Connect/Disconnect to First Bluetooth Equipment
<Keyboard Modes> Standard Mode: Standard Mode FN + Q (Driver Mode): Q White Light LED FN + W (Layer 1): W Light White LED FN + E (Layer 2): E Light White LED FN + R (Layer 3): R Light White LED