반응형

 

opensearch 무료지만 가이드가 너무하네

 

OpenSearch Dashboard Operator로 설정시  readolny 설정

대충입력하면 배열로 입력하라는데 아래와 같이 입력해야함.

다른 설정도 배열과 같이 입력하라면 아래와 같이 쌍따옴표 및 대괄호해서 입력하면 됨.

진짜 가이드 너무할정도로 별로임...

apiVersion: opensearch.opster.io/v1
kind: OpenSearchCluster
#...
spec:
  dashboards:
    additionalConfig:
      opensearch_security.readonly_mode.roles: "['readonly']"
반응형
반응형

 

k8s cluster를 kubernetes admin을 사용하는게 아닌 인증서를 통한 사용자를 생성하여 k8s cluster를 사용하는 방법이다.

 

1. 개인키 생성

# key 생성
openssl genrsa -out pangyeon.key 2048

# csr 생성
openssl req -new -key pangyeon.key -out pangyeon.csr -subj "/CN=pangyeon"

# csr 값 조회
cat pangyeon.csr | base64 | tr -d "\n"
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1dEQ0NBVUFDQVFBd0V6RVJNQThHQTFVRUF3d0ljR0Z1WjNsbGIyNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGpFa0FaSmhBdElhcTEzSjczREFsa1R4cUExeGdQRWx6dkxXbEVzdzdLCjBRQ29YMGdBR3JFVTlQcDNubWl2U051T0dKd0F4REN3dFQ1TThteDd2a21ZNHRPRC80ZWhVVGhQd3FhOXMwUjMKUUQ5SHlWQ0hqcm1PV1ZDempmNWJ5WkJXc3RZSjZxcGQ2ZUc2NVRlbDF0RmdNRHM4QUdsNmNiazJ4SE1WK2s2dQpNTkVsV3FnRGUwTmt1S3hLWW5OZnY5QWVRanlSek1NUm5Ia1c0cTNucFRqaXhnWTY4eFhzdHpQUlpTZ0YwVU8wCjdUdjlSRE5VdlVKQ3NBdzlrSFlObXdGWkw3SHNtcHdHV3lNdWRCVVVBQ0w3dFUyL0MwZFQ2VkpuSzBmV1VnVlMKNWtRK0NkdW5BdHVDTm8xOTdLS2hQalR5OXE3c1NnajVlcmltNEtGNkdIN2hBZ01CQUFHZ0FEQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBMnJxbHFGTHJjVUhkRU5qclQvVkxOUE5IVEFNMElyTEROVlVsWFRBSDA5S1JQZCsvCkNyUkF3TVEzOXJqRjE5R213Y1czZHNnSkRXR2NacXcxV1JTRlplQy9UaklJZXUzM0EvRm55TC8vYXVUZWg5REEKaEROcURTdnZpNEQzbmwyOTVGNFVMdzJVZG9QbTRyaWxzUHh0eEU3U1dUSFlpYm90QmZnSjJ2NUExb085UU5JeAo4NUE0eHJBVEEvR1EycWZhSlRhZ2pSUGQrNUVHK0tkTm85cnN0Vjl2Y3ZyTkdzS2F0YXpYL2dCTEhoWW9EMzVXCjJ0UFBCSUhmSUU4UUtmakJtZGJKQzlMY2o2UU00V2FDOVJRd293KzFEbTMwZnhmRjWVMVUszckVac3MKU21xVFphZFpWek9XWDdEQnVzM1A5V3lWOExU

 

 

2. CertificateSigningRequest 생성

# CertificateSigningReques 생성
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: pangyeon
spec:
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQTUEwR0NTcUdTSWIzUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRGpFa0FaSmhBdElhcTEzSjczREFsa1R4cUExeGdQRWx6dkxXbEVzdzdLCjBRQ29YMGdBR3JFVTlQcDNubWl2U051T0dKd0F4REN3dFQ1TThteDd2a21ZNHRPRC80ZWhVVGhQd3FhOXMwUjMKUUQ5SHlWQ0hqcm1PV1ZDempmNWJ5WkJXc3RZSjZxcGQ2ZUc2NVRlbDF0RmdNRHM4QUdsNmNiazJ4SE1WK2s2dQpNTkVsV3FnRGUwTmt1S3hLWW5OZnY5QWVRanlSek1NUm5Ia1c0cTNucFRqaXhnWTY4eFhzdHpQUlpTZ0YwVU8wCjdUdjlSRE5VdlVKQ3NBdzlrSFlObXdGWkw3SHNtcHdHV3lNdWRCVVVBQ0w3dFUyL0MwZFQ2VkpuSzBmV1VnVlMKNWtRK0NkdW5BdHVDTm8xOTdLS2hQalR5OXE3c1NnajVlcmltNEtGNkdIN2hBZ01CQUFHZ0FEQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBMnJxbHFGTHJjVUhkRU5qclQvVkxOUE5IVEFNMElyTEROVlVsWFRBSDA5S1JQZCsvCkNyUkF3TVEzOXJqRjE5R213Y1czZHNnSkRXR2NacXcxV1JTRlplQy9UaklJZXUzM0EvRm55TC8vYXVUZWg5REEKaEROcURTdnZpNEQzbmwyOTVGNFVMdzJVZG9QbTRyaWxzUHh0eEU3U1dUSFlpYm90QmZnSjJ2NUExb085UU5JeAo4NUE0eHJBVEEvR1EycWZhSlRhZ2pSUGQrNUVHK0tkTm85cnN0Vjl2Y3ZyTkdzS2F0YXpYL2dCTEhoWW9EMzVXCjJ0UFBCSUhmSUU4UUtmakJtZGJKQzlMY2o2UU00V2FDOVJRd293KzFEbTMwZnhmRjdUN05XdWVMVUszckVac3MKU21xVFphZFpWek9XWDdEQnVzM1A5V3lWOExUOFZKVG1H
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
EOF

# 생성한 CertificateSigningRequest 조회
kubectl get csr
NAME       AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
pangyeon   48s   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending

# 승인 요청
kubectl certificate approve pangyeon

# 승인확인
kubectl get csr
NAME       AGE     SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
pangyeon   5m17s   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Approved,Issued

# 승인한 인증서 추출
kubectl get csr pangyeon -o jsonpath='{.status.certificate}'| base64 -d > pangyeon.crt

 

 

3. Cluster Role 생성

해당 예시는 모든 자원에 대해 View 권한 부여

# CluserRole, CluserRolebinding 생성
vi role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: read-only
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-only-binding
subjects:
- kind: User
  name: pangyeon
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: read-only
  apiGroup: rbac.authorization.k8s.io
  
# 적용
kubectl apply -f role.yaml

 

 

4. Contexts 생성

# Credentials 생성
kubectl config set-credentials pangyeon --client-key=pangyeon.key --client-certificate=pangyeon.crt --embed-certs=true

# Context 추가
kubectl config set-context pangyeon --cluster=kubernetes --user=pangyeon

# 조회
kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin   
          pangyeon                      kubernetes   pangyeon
          
# 사용
kubectl config use-context pangyeon
Switched to context "pangyeon".

 

 

5. 테스트

조회시 인증서로 추가된 부분 확인 및 권한으로 인해 조회만 가능하고 삭제 불가

# 조회시 인증서로 계정 추가된 것 확인
cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJSFl4OUR6MmlDUHN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QkpoeWJCdElXSE1KRHY4WUtlQ2o0SEJ3MzlKT0E5MXJwcld0UURlUE4KYzRwWEZVMTQ5L1VZTSs2Q3hLZUtVTXphK0EyQU9vRzFMbUhzbzZYMktEYm5TRFlidFk2dDVLNFBlUmI1NXhMbAplRnZ5eDlzKzgxc0RZZGZVSlFVSlR4TEo1em9VOFlPQldhWjRrdUJObkF1TVJkbE40LzNCNnNwNkUrOXY2TDB2ClVGelpqYmhocFJyZjJ0TmZJV2hiU3Q4am9xcCtWc2hRMDZIN09WUU5nR1BwNGxxZGR5ZGJ4aGhKYWJvbnJMZ2oKTTF0elU0UFVadjFDVjh3dWRHclV4dDIxNkgwSC83SGN5UHRMWnE4MmpWOGl1Zk9FQzV5OFd5VHBBL25mcDJaNAp6RmR2ZjdpdkRaSXFhUjJQSTVScUxxeGNDOEJoQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRd0hCQ0NJRHJZQ29OckRIancyNXVVOSs3RTFqQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQThvZ1lQVjQrZwo5cHEwN0FZUStzbittdmNaVi93ZE9wbml3bkt1NXBBY1plWG1aQU1wOExEaUcwRWJ5RkJFdlNqWTZ6RmxIa2xmCjZNRE1QM1NPVXl0cmZ2Qnd5ZEpVdjNtOXNKOXdpYU1OY0RCekJXdlFNZ0NPQktWWXB2UTZHY05UOGEvdWV5UDYKVC9rQnNyeXhLNDV4OWMvSXRCVHVoOTdzMFgvTkthNHd2eTVJelg0YmZzVkJrVHpQdTVlRVRPZmtoWWY2aUxLNgpBV0ZiQWJWTUN0NWxsWFdxb2VtRm4wRm9ERDROdjV3ejQ0M3FmSTVRTktaQlBMUHZFTXMwMEo2RHNJY1NjOUoxCnpET3hWTVRJUk5ieUpWMk5GV2hYdXlLTUNUS05iUzgraGgvazVTVk41TUc3ZjBSVUdmSm1XV2N2SE0zS3Q5RXIKNitEREJ6aHgyZVppCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://127.0.0.1:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: pangyeon
  name: pangyeon
current-context: pangyeon
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJWUxSTnZQOFl4Qnd3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRFd016QXhORFF4TWpkYUZ3MHlOVEV3TXpBeE5EUTJNamRhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDZ2xVWmkKYWFweHBaYWdTT2wvcnpTckkzaWJFbUFpa2cyMVNqUGVMMXQ1U21jeEVINnNjUVZTcjV5REd4WUI1ZElLa0lrNwpSN0oyUGVlQi92RFFmbXdrUEQrUlE2bnFkS1QyM0c3R09QeDJla2pwcnJ2ejd4T0xjNGJDVURPTWVGcXl4TjVqClIrZTVSM2w1S3NQU2NxUUs4cTlDSUNVUXJ2NVplYVV1TW96NnFWQXZ3ZWtwZzNZanM2STlwWjJrWTEwTzRwYVAKZHRJTHcyU1NYSUR6YWNCa2txVy9SM1ZUR3ZNdHlqU1Nwak9YMVBwNkEwbHJOaUl1RzA5cDhOanI2U1VsMlptSwpvWGZweXBRV2p2UUJ4aUVXTVB1M2lqcTY3cmhQUVlhTWFmMzJjWmRhRHpFNHBqaTMxS2habWxUTCtlZS9YanhoClZwcWY2MmZIUFVyb01HMkxBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkRBY0VJSWdPdGdLZzJzTQplUERibTVUMzdzVFdNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUIrSys4MGVkNWJzNDhNM09acXBtbVdhNmdiCnd5bXl2c3BCZ1JNSGNLQXNMNTNuejNOaytYcDJZRUp1R3h2TDR4RlR0RWUxalhxRzRidkowUWJQcGhtdi9JRkEKWWJHUGNQU3YzMDR2WWhLcnBPMlc3NkE2ZUtFUUFxcS9YVzFaK0VTNEhMTUFYQWtLNzZ0dXNXV3lmY3pxb2NJMwpoYTc2bklBSjA5dkR6VlJQb2VWVGV4TmdWdEYvSFR5b1B1cGFaREhBV1FtOTBPUlduQmM4dHR5Z1pQdU4rVVI0CnFRYTJqRDJySmQ2UXREMUFTT2hkOFNtTHpJTkNBYlVtdXhTZXVZVkNHSy9oUWlWZS9EYVRPL1V4VXRUZStDb1oKYmFNbHBKNk96dVFQZzRZQVBsUXFvYisvSW1hSlVablFPYzdWQWxzN3QwWFEvTDF6Mmpxb0N4OWovcW56Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBb0pWR1ltbX
- name: pangyeon
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrRENDQWVDZ0F3SUJBZ0lRTno0OVVBM2h5QUlVZFY5NUVDbVdQakFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1CNFhEVEkwTVRFeU9URTBNVGN5TWxvWERUSTBNVEV6TURFMApNVGN5TWxvd0V6RVJNQThHQTFVRUF4TUljR0Z1WjNsbGIyNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRGpFa0FaSmhBdElhcTEzSjczREFsa1R4cUExeGdQRWx6dkxXbEVzdzdLMFFDb1gwZ0EKR3JFVTlQcDNubWl2U051T0dKd0F4REN3dFQ1TThteDd2a21ZNHRPRC80ZWhVVGhQd3FhOXMwUjNRRDlIeVZDSApqcm1PV1ZDempmNWJ5WkJXc3RZSjZxcGQ2ZUc2NVRlbDF0RmdNRHM4QUdsNmNiazJ4SE1WK2s2dU1ORWxXcWdECmUwTmt1S3hLWW5OZnY5QWVRanlSek1NUm5Ia1c0cTNucFRqaXhnWTY4eFhzdHpQUlpTZ0YwVU8wN1R2OVJETlUKdlVKQ3NBdzlrSFlObXdGWkw3SHNtcHdHV3lNdWRCVVVBQ0w3dFUyL0MwZFQ2VkpuSzBmV1VnVlM1a1ErQ2R1bgpBdHVDTm8xOTdLS2hQalR5OXE3c1NnajVlcmltNEtGNkdIN2hBZ01CQUFHalJqQkVNQk1HQTFVZEpRUU1NQW9HCkNDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3SHdZRFZSMGpCQmd3Rm9BVU1Cd1FnaUE2MkFxRGF3eDQKOE51YmxQZnV4Tll3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUZVRXlwNU1HS29YbmUzWjBRSG56N2ZZYVd3OAoyRE14SUdhWGZnSFR5dFlMM01SUGhqYlNXQXl1d0Z5alFSRVhWNTdIMm1iYTY2YjF6eDRvcHhTUFRXRFBValFjCkJ5bkg0b1c4TUs0b1BWSXJzWU9YcUVjVlZqZUhndEcwN1VCb0lTZlhvRnc4dWEwNS9EczJmaVhQbDZXSVpwSTYKTGovY2hhd25rSG8vbnk4QTVaWTRIbVI1UjdXL09uSnlmbW9BN244c3hydzhCN2NURXdpajgxUTBLbWtVT2crNgp2MVdwQlE0MHZMRWZUSnJuczE4TitxOW94Sk5SOGNRY2ZhW
    client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRGpFa0FaSmhBdElhcTEKM0o3M0RBbGtUeHFBMXhnUEVsenZMV2xFc3c3SzBRQ29YMGdBR3JFVTlQcDNubWl2U051T0dKd0F4REN3dFQ1TQo4bXg3dmttWTR0T0QvNGVoVVRoUHdxYTlzMFIzUUQ5SHlWQ0hqcm1PV1ZDempmNWJ5WkJXc3RZSjZxcGQ2ZUc2CjVUZWwxdEZnTURzOEFHbDZjYmsyeEhNVitrNnVNTkVsV3FnRGUwTmt1S3hLWW5OZnY5QWVRanlSek1NUm5Ia1cKNHEzbnBUaml4Z1k2OHhYc3R6UFJaU2dGMFVPMDdUdjlSRE5VdlVKQ3NBdzlrSFlObXdGWkw3SHNtcHdHV3lNdQpkQlVVQUNMN3RVMi9DMGRUNlZKbkswZldVZ1ZTNWtRK0NkdW5BdHVDTm8xOTdLS2hQalR5OXE3c1NnajVlcmltCjRLRjZHSDdoQWdNQkFBRUNnZ0VBTzBQYktQVXZTYWc4MXdTREZQVzJTZEQvbU5zSzgzd1dkM0tCeENWNzJlR2MKNjFVYkJMUHl2Z2FHak12eWhMVmVZSUw1ekpWb0krYmFJTmt4Q1VjTURIUS9RbmRpSGUrRjVBTm80NkF6WVhDSwpVNkV1ZklMNjJUVmtnOGl1dDZRdklRSENMWXBxOXVJQlFYZHNBOFBDbC9sZXJIVnJFa00yVlI0Rzc1aUtDcHBECk9hSzB0VWJPWnNkQnlHOWg2eWF0Wk90cVhOMktKSzVJK0J4dVpnVHMxUGhENHNqSnBBRUxhb3M4dHFicG56cDEKNDZYZUtjTlU1Ky9FSHBwaEdTdEExRzdLRDBaSWVHRmZ6SEdFUmk3aXVhZzEvV1hjdk9Cc3I2NXd1U3NyYU1QVApIRTNkcXNoUXdNK1dDYlQ1djBtWFMrRWdOWFN5SXRUQXpydVk4MWMxQlFLQmdRRDZjNlZSV1gyQzBISEpQWHBsCkdiaTJ2cmQwY1NseTY2VEJnc0xkYzdZYWdmQ0VTY3BBQTFuWEQrRWR4V29MS084UGl3S0ZVbUJqZFI4NVk2NXIKakdObGN2NytwRmJSZ3dXZjk5TzZsdjE0Ty80RXdUWkF3ZjRnSHlGKzRodUJScjBJL0loa0cyRmV2WmZ6RWdOWApLSExLRVJwVEJCU0h6SVZ0UEVVUk5YbWxId0tCZ1FEb0dnS1hBVGo2bzlqWWZSODNjQ1l3Njk2cUFzdmpCbTFVCkJDdnQ3ZzRPY00wN3UrWW5hKytuQm5pYUZJY0JZTzd2b3VMUGhrVGlXSlFTREhKcFIxWkNtWGFaMXFaZERjNHIKT283TldFZlFKRXAvOEdFck9nRDJ6YXZSNk9LUGl1dyt6UTE2V1hMamxkQ0lpRVc4UVN5cEM2dW9Oa0tYWUxxRApGWWhkeldWYi93S0JnUURWeGM0dkVLYWIrTldXd3Izcys3WjViWEpqbG8rZGd0dGZQUUNkU3ozOWhEbktnTDE4ClJCL3ovSjdXN1lGbFF5eENaUkhpd0h4N2lDWDlzMExXazc3bmdlOTdaTVNpRWliRDh5SXJHdVFCTTV2UGJTZWsKd0xEcnRBYkFLYmoyY0cyNzlPbHFJU0RNWUNJSm5LOXpQcGcwTjhMelp3RXJKSHdpMEJYWDZZQUtXd0tCZ0g3TApSc0xyZmc4ZVZ5WGRKS0tLZDdLZUNDUGtKekc4bnhrWXRrN2lqM2RBRkQ0ZnBkbS9VMHB4ZEl6bnplRG83VjZvCkl6T3ZiQTRpeWJFYWI1NG54RzNabkRycVVqUGZpTk9BeCtaUjVkbEZHaFhPWWFiVnB4VXN3a0tIOE16dDNhVnAKSzRXOU85QXNWYUZnb0lmNUtzYW1nMzMvTmwyd0QvUHdYWEN3OWtCTkFvR0JBSldScDk0OW1CcU1za2lwTzNhWAp5NnNuYlJ2Y3JhdmJFTUx2UHdISmRJdVg2Kzg0WGdUcHRwREJVZWpyRkhZM1FmVXA2VytnSngzaHFnOTQwV2I1CnhEM2lNblVzamhoZW4vSmtwN3Fma25SWmVGRUdTVVZ
    
# 조회
kubectl get pods
NAME                           READY   STATUS 
stdout-node-6f945d7989-6xjp2   1/1     Running 

# Read권한만 있어 삭제 불가
kubectl delete pods stdout-node-6f945d7989-6xjp2 
Error from server (Forbidden): pods "stdout-node-6f945d7989-6xjp2" is forbidden: User "pangyeon" cannot delete resource "pods" in API group "" in the namespace "default

 

 

참고 : https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user

반응형
반응형

 

OpenSearch Operator 설치시 인증서 설정하는 방법이다.

(가이드가 진짜 너무 너무 심하게 불친절하게 되어있음.... )

 

1. 먼저 자체 서명 인증서를 생성한다.

가이드에는  딱히 어떻게 뭘 생성하라는 얘기는 없으며, 인증서가 하나만 있으면 된다고 나와있으나

사실상 root-ca 와 Admin 인증서, Node 인증서가 필요하다.

또한, adminSecret 역시  tls.crt와 tls.key만 있으면 된다고 나와있지만 ca.crt 가 필요하며,

각종 필드에 대한 설명들이 많이 부족하다.

 

Admin인증서의 경우 OpenSearch Operator가 OpenSearch Cluster를 관리하는관리자 인증서이며,

Node 인증서의 경우 OpenSearch Node 인증서이다. Node인증서는 각 Node별로 만들어서 관리할 수 있으나,

해당 가이드는 하나만 만들어서 공유하는 방법이다.

 

subjectAltName에 들어가는 내용들은 OpenSearch cluster 설치시 포함되는 metadata의 name기준으로 만들어야하며,

OpenSearch Cluster가 생성되면서 뒤에 masters가 붙기 때문에 masters는 반드시 포함한다.

# root ca 생성
openssl genrsa -out root-ca-key.pem 2048
openssl req -new -x509 -sha256 -key root-ca-key.pem -subj "/CN=opensearch" -out root-ca.pem -days 3650

# OpenSearch Operator가 OpenSearch Cluster를 관리하는 관리자 인증서
openssl genrsa -out admin-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
openssl req -new -key admin-key.pem -subj "/CN=opensearch-admin" -out admin.csr
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 3650

# Node간 DNS 통신을 위해 subjectAltName 생성
echo 'subjectAltName=DNS:opensearch-cluster-masters,DNS:opensearch-cluster-masters.opensearch,DNS:opensearch-cluster-masters.opensearch.svc,DNS:opensearch-cluster-masters.opensearch.svc.cluster.local' > san.ext

# OpenSearch Node간 인증서
openssl genrsa -out node-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in node-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node-key.pem
openssl req -new -key node-key.pem -subj "/CN=opensearch-cluster-masters" -out node.csr
openssl x509 -req -in node.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node.pem -days 3650 -extfile san.ext

# OpenSearch yaml에 등록할 인증서 파일들 secret으로 생성
kubectl create secret generic opensearch-cert-admin --from-file=ca.crt=root-ca.pem --from-file=tls.crt=admin.pem --from-file=tls.key=admin-key.pem -n opensearch
kubectl create secret generic opensearch-cert-node --from-file=ca.crt=root-ca.pem --from-file=tls.crt=node.pem --from-file=tls.key=node-key.pem -n opensearch

 

 

2. OpenSearch Cluster를 생성할 yaml파일 작성

securityConfig 에는 OpenSearch Operator가 OpenSearch Cluster를 관리하는관리자 인증서를 추가해야하며,

transport secret과 http secret dashboard의 tls secret에는 Node 인증서를 추가하면된다.

그리고 metadata name과 위에 생성한 subjectAltName에 포함된 DNS의 이름과 맞춰주어야 한다.

nodesDn은 root-ca에 생성한 subj 를 입력하고 wildcard를 추가해도된다.

adminDn은 관리자 인증서 생성할 때 입력하였던 subj를 추가한다.

apiVersion: opensearch.opster.io/v1
kind: OpenSearchCluster
metadata:
  name: opensearch-cluster
  namespace: opensearch
spec:
  security:
    config:
      adminSecret:
        name: opensearch-cert-admin
    tls:
       http:
         generate: false
         secret:
           name: opensearch-cert-node
       transport:
         generate: false
         perNode: false
         secret:
           name: opensearch-cert-node
         nodesDn: ["CN=opensearch-cluster-masters*"]
         adminDn: ["CN=opensearch-admin"]
  general:
    httpPort: 9200
    serviceName: my-first-cluster
    version: 2.14.0
    pluginsList: ["repository-s3"]
    drainDataNodes: true
  dashboards:
    tls:
      enable: true
      generate: false
      secret:
        name: opensearch-cert-node
    version: 2.14.0
    enable: true
    replicas: 1
    resources:
      requests:
         memory: "512Mi"
         cpu: "200m"
      limits:
         memory: "512Mi"
         cpu: "200m"
  nodePools:
    - component: masters
      replicas: 3
      resources:
         requests:
            memory: "4Gi"
            cpu: "1000m"
         limits:
            memory: "4Gi"
            cpu: "1000m"
      roles:
        - "data"
        - "cluster_manager"
      persistence:
         emptyDir: {}

 

이후 해당 yaml파일을 적용하면 문제없이 생성된다.

 

참고로 tls transport 는 반드시 인증서를 적용해주어야 한다.(필수임)

반응형
반응형

Containerd 에서 인증서 에러 발생시 인증서가 있는 경우와 없는 경우 설정하는 방법이다.

 

참고로 containerd 를 설정했다고 ctr 명령어 까지 같이 적용되는건 아니다. crictl 만 적용된다.

ctr 의  경우 인증서가 있으면 --tlscacert, --tlscrt, --tlskey 3개옵션을 적용하여 사용하면 되며

인증서가 없을 경우 --skip-verify 옵션을 사용하면된다.

 

1. containerd 설정파일을 수정한다.

$ vi /etc/containerd/config.toml

[plugins."io.containerd.grpc.v1.cri".registry]
   config_path = "/etc/containerd/certs.d"

 

2. certs.d 폴더를 생성한다.

$ cd /etc/containerd/

$ mkdir certs.d

 

3. 내부에 인증서 연결할 서버 폴더생성

$ cd certs.d

$ mkdir registry.wky.kr

$ cd registry.wky.kr

$ pwd
/etc/containerd/certs.d/registry.wky.kr

 

 

4. hosts.toml 파일 생성 

인증서가 있는 경우.

$ vi hosts.toml

server = "https://registry.wky.kr"

[host."https://registry.wky.kr"]
  capabilities = ["pull", "resolve"]
  # pemfile 이 있는 경로 및 파일 입력
  ca = pemfile.pem
  # crt, key, pem 파일이 있는 경로 및 파일 입력
  client = [[crtfile.crt, keyfile.key], [pemfile.pem]]

 

인증서가 없는 경우

$ vi hosts.toml

server = "https://registry.wky.kr"

[host."https://registry.wky.kr"]
  capabilities = ["pull", "resolve"]
  skip_verify = true

 

 

 

참고 : https://github.com/containerd/containerd/blob/main/docs/hosts.md

반응형
반응형

 

Container 실행없이 이미지 내에 있는 파일들을 확인하는 방법이다.

'ctr image mount imagename:tag 폴더' 명렁어를 통해 확인할 수 있다.

 

먼저 이미지가 서버 내에 있어야함.

$ crictl images
IMAGE                                    TAG                 IMAGE ID            SIZE
docker.io/library/busybox                latest              63cd0d5fb10d7       1.86MB

$ mkdir busybox

$ ctr -n=k8s.io image mount docker.io/library/busybox:latest ./busybox/
sha256:66ccab9b46d8f9daffd6e24c69ab2d6c5a5b44e9d0e39991985a910a2775755e
./busybox/

$ ls busybox/
bin  dev  etc  home  lib  lib64  root  tmp  usr  var

 

반응형
반응형

 

간단하게 인증서 설정없이 Docker Private Registry를 k8s에 설치하는 방법이다. 설치 후 UI 적용할 예정.

 

1. id, password 생성 (굳이 안 해도 됨)

 nerdctl run --entrypoint htpasswd   httpd:2 -Bbn testuser testpassword > auth/htpasswd

 

 

2. namespace 생성 및 secret 생성

$ kubectl create ns registry
$ kubectl create secret generic registry-auth --from-file=idpass=./htpasswd -n registry

 

 

3. pv, pvc, deployment, service 생성

storageclass가 없을 경우 pv를 생성하고 workernode에 registry폴더를 생성한다.(해당 경로는 적절히 수정해서 사용하면 됨)

1번에 id, password 생성 하지 않았으면, deployment 내 registry-auth 부분들 삭제하고 진행

아래 yaml 생성 후 kubectl apply -f registry.yaml -n registry 명령어 실행

$ vi registry.yaml
$ kubectl apply -f registry.yaml -n registry

apiVersion: v1
kind: PersistentVolume
metadata:
  name: registry-pv
  labels:
    reg: registry
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: "/root/registry"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  labels:
    reg: registry
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      reg: registry
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry
  labels:
    reg: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      reg: registry
  template:
    metadata:
      labels:
        reg: registry
    spec:
      containers:
      - name: registry
        image: registry:2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: registry-auth
          mountPath: /auth # 이미지 내 기본 registry auth 경로
        - name: registry-data
          mountPath: /var/lib/registry
        env:
        - name: REGISTRY_AUTH_HTPASSWD_PATH # 기본 설정
          value: /auth/idpass # secert에 들어가는 파일을 idpass로 생성
        - name: REGISTRY_AUTH_HTPASSWD_REALM # 기본 설정
          value: "Registry Realm"
        - name: REGISTRY_STORAGE_DELETE_ENABLED
          value: "true"
      volumes:
      - name: registry-auth
        secret:
          secretName: registry-auth
      - name: registry-data
        persistentVolumeClaim:
          claimName: registry-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: registry
spec:
  type: NodePort
  ports:
    - port: 5000
      targetPort: 5000
      nodePort: 30050
      protocol: TCP
  selector:
    reg: registry

 

 

4. 테스트

curl localhost:30050/v2/_catalog -u "testuser:testpassword"

 

 

5. UI 적용 (UI가 굳이 필요없으면 안 해도 됨)

UI 는 아래 오픈소스를 사용할 예정이다.

https://github.com/Joxit/docker-registry-ui

 

우선 위에 생성한 registry 에 ingress 를 등록해야한다. (Domain이 일치해야 UI에서 인증을 사용할 수 있음.)

$ vi registry-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry
  nginx.ingress.kubernetes.io/proxy-body-size: 4096m # 이미지 업로드 용량으로 반드시 설정필요하며 필요에 따라 설정
spec:
  ingressClassName: nginx
  rules:
  - host: registry.wky.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: registry
            port:
              number: 5000

 

또한, 위에 생성한 Deployment에 환경변수를 추가해야한다.

  $ kubectl edit deploy -n registry registry
  ...
      - env:
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin # 추가
          value: '[http://registry-ui.wky.kr:30080]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods # 추가
          value: '[HEAD,GET,OPTIONS,DELETE]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials # 추가
          value: '[true]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers # 추가
          value: '[Authorization,Accept]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers # 추가
          value: '[Docker-Content-Digest]'
        - name: REGISTRY_STORAGE_DELETE_ENABLED
          value: "true"
        - name: REGISTRY_AUTH_HTPASSWD_PATH
          value: /auth/idpass
        - name: REGISTRY_AUTH_HTPASSWD_REALM
          value: Registry Realm     
  ...

 

UI 설치

특히 아래 yaml의 NGINX_PROXY_PASS_URL은 k8s service domain을 넣거나 nodeport를 넣거나 ingress를 넣어주면된다.

$ vi registry-ui.yaml
$ kubectl apply -f registry-ui -n registry

apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry-ui
  labels:
    reg: registry-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      reg: registry-ui
  template:
    metadata:
      labels:
        reg: registry-ui
    spec:
      containers:
      - name: registry-ui
        image: joxit/docker-registry-ui:main
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        env:
        - name: SINGLE_REGISTRY
          value: "true"
        - name: REGISTRY_TITLE
          value: Docker Registry UI
        - name: DELETE_IMAGES
          value: "true"
        - name: SHOW_CONTENT_DIGEST
          value: "true"
        - name: SHOW_CATALOG_NB_TAGS
          value: "true"
        - name: CATALOG_MIN_BRANCHES
          value: "1"
        - name: CATALOG_MAX_BRANCHES
          value: "1"
        - name: TAGLIST_PAGE_SIZE
          value: "100"
        - name: REGISTRY_SECURED
          value: "true"
        - name: CATALOG_ELEMENTS_LIMIT
          value: "1000"
        - name: NGINX_PROXY_PASS_URL
          value: http://registry.registry:5000 #  http://registry.wky.kr:30050 또는 http://registry.wky.kr:30080
        - name: REGISTRY_SECURED
          value: "true"
---
apiVersion: v1
kind: Service
metadata:
  name: registry-ui
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30051
      protocol: TCP
  selector:
    reg: registry-ui
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry-ui
spec:
  ingressClassName: nginx
  rules:
  - host: registry-ui.wky.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: registry-ui
            port:
              number: 80

 

결과 확인

 

기타 : https 로 여는법

사설 인증서를 생성하고, 사설인증서이기 때문에 해당 registry를 실제 사용할 서버를 위해 ca파일도 생성한다.

# 사설 인증서 생성
$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout domain.key -subj "/CN=registry.wky.kr" -addext "subjectAltName=DNS:registry.wky.kr" -x509 -days 365 -out domain.crt

# 이미지 push 또는 pull 위한 ca 파일 생성
$ cat domain.crt domain.key > domain.pem

 

registry에 마운트할 secret과 ingress에 등록할 secert 2개를 생성한다.

# registry 인증서용
$ kubectl create secret generic https-registry --from-file=domain.crt=./domain.crt --from-file=domain.key=./domain.key -n registry
 
# registry ingress용
$ kubectl create secret tls tls-registry --key ./domain.key --cert ./domain.crt -n registry

 

deployment와 service, ingress 수정

# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry
  labels:
    reg: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      reg: registry
  template:
    metadata:
      labels:
        reg: registry
    spec:
      containers:
      - name: registry
        image: registry:2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 443 # 443으로 수정
        volumeMounts:
        - name: registry-auth
          mountPath: /auth 
        - name: registry-data
          mountPath: /var/lib/registry
        - name: https-registry # 인증서파일 마운트
          mountPath: /tmp
        env:
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin
          value: '[http://registry-ui.wky.kr:30080]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods 
          value: '[HEAD,GET,OPTIONS,DELETE]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials 
          value: '[true]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers
          value: '[Authorization,Accept]'
        - name: REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers 
          value: '[Docker-Content-Digest]'
        - name: REGISTRY_STORAGE_DELETE_ENABLED
          value: "true"
        - name: REGISTRY_AUTH_HTPASSWD_PATH
          value: /auth/idpass
        - name: REGISTRY_AUTH_HTPASSWD_REALM
          value: Registry Realm     
        - name: REGISTRY_STORAGE_DELETE_ENABLED
          value: "true"
        - nmae: REGISTRY_HTTP_TLS_CERTIFICATE # 인증서 설정
          value: /tmp/domain.crt
        - name: REGISTRY_HTTP_TLS_KEY  # 인증서 설정
          value: /tmp/domain.key
        - name: REGISTRY_HTTP_ADDR # 443으로 포트 열기
          value: 0.0.0.0:443
      volumes:
      - name: registry-auth
        secret:
          secretName: registry-auth
      - name: registry-data
        persistentVolumeClaim:
          claimName: registry-pvc
      - name: https-registry # 인증서 secret 마운트
        secret:
          secretName: https-registry
 
# serivce 
apiVersion: v1
kind: Service
metadata:
  name: registry
spec:
  type: ClusterIP # NodePort도 관계없음.
  ports:
    - port: 443 # 443으로 수정
      targetPort: 443  # 443으로 수정
      protocol: TCP
  selector:
    reg: registry
    
# ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry
  nginx.ingress.kubernetes.io/backend-protocol: HTTPS # HTTPS 통신
  nginx.ingress.kubernetes.io/proxy-body-size: 4096m 
spec:
  ingressClassName: nginx
  rules:
  - host: registry.wky.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: registry
            port:
              number: 443
  tls: # tls secret 마운트
  - hosts:
    - registry.wky.kr
  secretName: tls-registry

 

 

참고 : 

https://distribution.github.io/distribution/

https://github.com/Joxit/docker-registry-ui

 

반응형
반응형

 

OpenSearch Install, OpenSearch Dashboard install 및 Fluent-Bit 연동이다.

OpenSearch 설치시 바로 Helm으로 설치할 경우 패스워드가 없어서 에러가 발생할 뿐만아니라, 데모 인증서가

설치안되는 경우가 있다. 이 경우는 따로 패스워드 설정 및 데모인증서가아닌 인증서를 넣어주면되는데,

마지막에 따로 추가적으로 설정하는 방법을 정리한다.

 

Fluent-Bit 연동은 10번부터, 데모 인증서가 아닌 인증서 설정은 기타부분을 참조한다.

Fluent-Bit 연동을 위해 설치는 아래 링크 참조

2024.11.01 - [Develop/k8s] - k8s fluent-bit install and standard out test

 

0. 로깅 대상 Pod 관련

fluent-bit의 경우 Pod 내 label 이 app: 으로 시작하는 경우 로깅을 하지 못하므로,

반드시 label이 app: 으로 되어있는게 없도록 변경해주어야한다.

 

 

1. 메모리 맵 영역 조정

메모리 맵 영역을 조정하지 않으면 설치 후 에러가 발생함.

모든 서버에 적용.

$ vi /etc/sysctl.conf

# 해당 항목 추가 또는 수정
vm.max_map_count=262144

# 적용
$ sudo sysctl -p

 

 

2. OpenSearch 설치

helm chart로 설치할 예정이므로 아래 사이트에 접속해 helm charts를 다운받는다.

(가이드에 나온대로 바로 helm repo를 추가하여 설치 할 수 있지만, 위에 설명한대로 데모인증서가 설치안되는 경우가 있음.

데모인증서가 설치 안될 경우 아래 기타 항목 참조)

https://github.com/opensearch-project/helm-charts/releases

$ tar -zxvf opensearch-2.26.1.tgz
$ cd opensearch

 

 

3. values.yaml 내 OPENSEARCH_INITIAL_ADMIN_PASSWORD 설정 

ADMIN_PASSWORD를 설정한다. 해당 패스워드 설정하지 않을 경우 설치시 설정하라고 에러 발생

또한, 패스워드를 강하게 설정해야한다. 대문자, 숫자, 특수문자가 들어가야하며, 쉬운패스워드는 또 되지 않는다.

처음에 주석으로 되어있고 extraEnvs: [] 대괄호가 있으므로 대괄호는 반드시 지운다.

$ vi values.yaml
extraEnvs:
  - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD
    value: wkyKr!2024

 

 

4. PV설정

기존 서버에 StorageClass가 설정되어있으면, 패스한다. 

StorageClass 가 없을 경우 PV를 설정해주어야한다. (PVC는 OpenSearch내에 적용되어 있음.)

모든 서버에 볼륨 폴더를 생성한다. (모든 서버에 할 필요는 없으나, 파드가 어디 서버에 동작될지 설정하지 않았으므로,

모든 폴더에 생성한다. 어디에 동작될지 설정할경우 해당 서버에만 폴더를 생성한다.)

 

opensearch가 statefulset으로 기본적으로 pod가 3개정도 동작하므로 pv를 미리 3개정도 만들어둔다.

아니면, helm install 후에 pvc와 pv 이름을 매칭하여 pv를 생성하고 pvc를 수정한다.

편한대로 진행하면됨.

# Worker Node가 2개뿐이라 2개씩 전부 생성
$ mkdir opensearch-pv
$ mkdir opensearch-pv2

 

pv 생성

$ vi pv-0.yaml
apiVersion: v1
metadata:
  name: opensearch-pv-0
  labels:
    service: opensearch-pv-0
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /root/opensearch-pv
 
$ vi pv-1.yaml
apiVersion: v1
metadata:
  name: opensearch-pv-1
  labels:
    service: opensearch-pv-1
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /root/opensearch-pv

$ vi pv-2.yaml
apiVersion: v1
metadata:
  name: opensearch-pv-2
  labels:
    service: opensearch-pv-2
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /root/opensearch-pv2
    
$ kubectl apply -f pv-0.yaml
$ kubectl apply -f pv-1.yaml
$ kubectl apply -f pv-2.yaml

 

 

5. helm install

3번의 values.yaml 수정하였으고 pv를 생성하였으면, 패키징 후 설치한다. (pv는 아래 먼저 실행 후 생성되는 것보고 맞춰서 생성해도 됨)

$ helm package .
$ helm install opensearch opensearch-2.26.1.tgz --create-namespace --namespace logging

# 실행확인
$ kubectl get pods -n logging
NAME                          READY   STATUS    RESTARTS   AGE
opensearch-cluster-master-0   1/1     Running   0          33m
opensearch-cluster-master-1   1/1     Running   0          33m
opensearch-cluster-master-2   1/1     Running   0          33m

 

 

6. 정상동작 확인

$ kubectl exec -it opensearch-cluster-master-0 -n logging -- /bin/bash
$  curl -XGET https://localhost:9200 -u 'admin:wkyKr!2024' --insecure
{
  "name" : "opensearch-cluster-master-0",
  "cluster_name" : "opensearch-cluster",
  "cluster_uuid" : "Iqk-kEIxRNWEvEXkCFX-BQ",
  "version" : {
    "distribution" : "opensearch",
    "number" : "2.17.1",
    "build_type" : "tar",
    "build_hash" : "1893d20797e30110e5877170e44d42275ce5951e",
    "build_date" : "2024-09-26T21:59:52.691008096Z",
    "build_snapshot" : false,
    "lucene_version" : "9.11.1",
    "minimum_wire_compatibility_version" : "7.10.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "The OpenSearch Project: https://opensearch.org/"
}

 

 

7. OpenSearch DashBoard 설치

OpenSeach와 마찬가지로 helm chart로 설치할 예정이므로 아래 사이트에 접속해 helm charts를 다운받는다.

https://github.com/opensearch-project/helm-charts/releases

 

다운 받았으면, 바로 실행한다.

$ helm install opensearch-dashboards opensearch-dashboards-2.24.1.tgz --create-namespace --namespace logging

# 실행 후 확인
$ kubectl get pods -n logging
NAME                                     READY   STATUS    RESTARTS   AGE
opensearch-dashboards-649d556895-r4vwn   1/1     Running   0          2m13s

 

 

8. OpenSearch DashBoard 접근을 위한 ingress 설정

$ vi ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: opensearch-dashboard
  namespace: logging
spec:
  ingressClassName: nginx
  rules:
  - host: os-dashboard.wky.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: opensearch-dashboards
            port:
              number: 5601
              
 $ kubectl apply -f ingress.yaml

 

 

9. 접속 확인

계정은 admin

패스워드는 3번에 설정한 패스워드 입력

 

 

10. Fluent-Bit 연동

먼저 Fluent-Bit 이 설치되어 있어야 한다. 설치방법은 아래 링크 참조

2024.11.01 - [Develop/k8s] - k8s fluent-bit install and standard out test

(위 링크에 따라 그대로 설정했으면 stdout 부분은 제거한다.)

OUTPUT 옵션은 필요에 따라 가이드보고 적용하며,

Host는 oepnsearch가 statefulset으로 동작하므로 opensearch service의 headless service로 연결한다.

$ kubectl edit cm fluent-bit
# [OUTPUT] 에 stdout이 있으면 해당 부분 제거 후 아래 부분 추가

   [OUTPUT]
        Name opensearch
        Match kube.*
        Host opensearch-cluster-master-headless.logging
        Port 9200
        tls On
        tls.verify Off
        HTTP_User admin
        HTTP_Passwd wkyKr!2024
        Retry_Limit False
        Suppress_Type_Name On

 

fluent-bit 의 config map hot reload 를 설정하지 않았으므로, fluent-bit pod를 전체 재기동한다.

 

11. 연동 후 OpenSearch에서 확인을 위해 서비스를 통한 로깅 테스트 후 Fluent-Bit 확인

2024.11.01 - [Develop/k8s] - k8s fluent-bit install and standard out test

해당 글에서 생성한 서비스의 로그가 잘 표시되는 것을 확인

 

 

기타. 데모인증서가 아닌 인증서 설정

helm 내의 values.yaml 를 수정하지 않고 바로 공식 가이드 대로 배포할 경우 패스워드도 없고 데모 인증서가 생성 되지 않을 경우가 있는데,

패스워드를 설정하고 인증서 생성 후 인증서는 pv에 넣어주면 된다.

 

1. 패스워드 설정

패스워드 설정은 statefulset의 환경변수에 입력해주면된다.

$ kubectl edit sts -n logging opensearch-cluster-master
...
containers:
      - env:
        - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD
          value: wkyKr!2024
...

 

 

2. PV는 있다고 가정 후 인증서 생성 (없을 경우 위 내용 중 4번 확인)

$ openssl genrsa -out root-ca-key.pem 2048
$ openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 730
$ openssl genrsa -out esnode-key-temp.pem 2048
$ openssl pkcs8 -inform PEM -outform PEM -in esnode-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out esnode-key.pem
$ openssl req -new -key esnode-key.pem -out esnode.csr
$ openssl x509 -req -in esnode.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out esnode.pem -days 730

 

 

3. 생성한 인증서 중 esnode.pem, esnode-key.pem, root-ca.pem 을 pv 폴더에 이동

OpenSearch pod 와 pv 간 mountPath가 안맞는 경우가 있어 statefulset 내 mountPath수정함.

또한 위 4번에서 생성한 opensearch-pv, opensearch-pv2 폴더내 config 폴더 생성

esnode.pem, esnode-key.pem, root-ca.pem 를 config 폴더에 이동

$ kubectl get sts -n logging opensearch-cluster-master -o yaml

# 수정 전
- mountPath: /usr/share/opensearch/config/opensearch.yml
  name: config-emptydir
  
# 수정 후
- mountPath: /usr/share/opensearch/data/config/opensearch.yml
  name: config-emptydir
  
$ mkdir ~/opensearch-pv/config
$ mkdir ~/opensearch-pv2/config

esnode.pem, esnode-key.pem, root-ca.pem 해당폴더로 복사한다

 

4. config map 수정

  allow_unsafe_democertificates: true -> false로 수정

$ kubectl edit cm -n logging opensearch-cluster-master-config -o yaml

# 기존에 true로 되어있음 false로 수정
allow_unsafe_democertificates: false

 

 

참고 :

https://opensearch.org/docs/latest/install-and-configure/install-opensearch/index/

https://opensearch.org/docs/latest/install-and-configure/install-opensearch/helm/

https://opensearch.org/docs/latest/install-and-configure/install-dashboards/helm/

https://opensearch.org/docs/latest/security/configuration/generate-certificates/

https://docs.fluentbit.io/manual/pipeline/outputs/opensearch

 

반응형
반응형

 

k8s에서 fluent-bit 설치 및 stdout 테스트이다. opensearch 설치 및 연동테스트는 아래 링크참조

2024.11.03 - [Develop/k8s] - OpenSearch, Dashboard 설치 및 Fluent-Bit OpenSeach 연동

 

 

0. 로깅 대상 Pod 관련

fluent-bit의 경우 Pod 내 label 이 app: 으로 시작하는 경우 로깅을 하지 못하므로,

반드시 label이 app: 으로 되어있는게 없도록 변경해주어야한다.

 

 

1. 우선 테스트할 서비스를 하나 생성한다

nodejs로 로깅 테스트 - https://github.com/wonkwangyeon/stdout-nodejs

java서비스로 로깅 테스트 - https://github.com/wonkwangyeon/stdout-java

 

 

2. 테스트 서버를 배포한다.

$ kubectl apply -f k8s.yaml
deployment.apps/stdout-node created
service/stdout-node-service created
ingress.networking.k8s.io/stdout-node-ingress created

$ kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
stdout-node-6f945d7989-6xjp2   1/1     Running   0          20s

 

 

3. fluent-bit install

$ helm repo add fluent https://fluent.github.io/helm-charts
$ helm upgrade --install fluent-bit fluent/fluent-bit

# namespace 를 주지않으면 default namespace에 생성된다
$ kubectl get pods
NAME                           READY   STATUS              RESTARTS   AGE
fluent-bit-67blm               0/1     ContainerCreating   0          5s
fluent-bit-vvt7c               0/1     ContainerCreating   0          5s

 

 

4. 현재 elasticsearch 나 opensearch 를 설치하지 않았으므로 stdout테스트를 진행한다. (테스트 후 opensearch 설치 예정)

기존에 있던 OUTPUT인 elasticsearch를 삭제하고 [OUTPUT]으로 stdout 을 추가한다.

(해당 Name의 경우 이름이 정해져있으며, 이름마다 사용할 수 있는 변수?가 다르다. 공식 가이드에서 확인 가능하다.)

$ kubectl edit cm fluent-bit

	기존에 있던 elasticsearch OUTPUT 삭제
    [OUTPUT]
        Name es
        Match host.*
        Host elasticsearch-master
        Logstash_Format On
        Logstash_Prefix node
        Retry_Limit False
        
    아래 stdout OUTPUT 추가
    [OUTPUT]
        Name stdout
        Match kube.*

# config map 수정 후 fluent-bit pod 삭제를 통해 재기동한다.
$ kubectl delete pods fluent-bit-67blm  fluent-bit-vvt7c
pod "fluent-bit-67blm" deleted
pod "fluent-bit-vvt7c" deleted

 

 

5. 1번에서 설치한 테스트 pod 위치를 확인 후 같은 위치의 fluent-bit pod 의 로그를 f option을 통해 확인한다.

이후 테스트 서비스를 호출하여 로그가 fluent-bit pod에 출력되는지 확인한다.

(OpenSearch 연동은 아래링크 참조 :

2024.11.03 - [Develop/k8s] - OpenSearch, Dashboard 설치 및 Fluent-Bit OpenSeach 연동)

# 테스트 서비스 위치 확인 (2번에 있는 것 확인)
$ kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
stdout-node-6f945d7989-6xjp2   1/1     Running   0          27m     10.0.2.9    worker2   <none>           <none>

# fluent-bit 위치 확인 (2번 fluent-bit pod 확인)
$ kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
fluent-bit-bng54               1/1     Running   0          6m41s   10.0.0.62   worker1   <none>           <none>
fluent-bit-crjlm               1/1     Running   0          6m40s   10.0.2.37   worker2   <none>           <none>

# 2번 fluent-bit 로그 출력
$ kubectl logs -f fluent-bit-crjlm  

# service 호출 후 아래 로그 확인
[0] kube.var.log.containers.stdout-node-6f945d7989-6xjp2_default_stdout-a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10.log: [[1730388117.989743401, {}], {"time"=>"2024-10-31T15:21:57.989743401Z", "stream"=>"stdout", "_p"=>"F", "log"=>"2024-10-31T15:21:57.989Z debug : Log Hello World", "kubernetes"=>{"pod_name"=>"stdout-node-6f945d7989-6xjp2", "namespace_name"=>"default", "pod_id"=>"037e0276-650f-460f-85cb-095ed4f65cd7", "labels"=>{"pod-template-hash"=>"6f945d7989", "stdout"=>"stdout-node"}, "host"=>"worker2", "container_name"=>"stdout", "docker_id"=>"a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10", "container_hash"=>"sha256:aff389fbc4cac45f0ca6de06328e7d51f1d887306a9c278d4349f61e281ac562", "container_image"=>"docker.io/stdout/node:latest"}}]
[1] kube.var.log.containers.stdout-node-6f945d7989-6xjp2_default_stdout-a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10.log: [[1730388117.989830525, {}], {"time"=>"2024-10-31T15:21:57.989830525Z", "stream"=>"stdout", "_p"=>"F", "log"=>"2024-10-31T15:21:57.989Z info : Log Hello World", "kubernetes"=>{"pod_name"=>"stdout-node-6f945d7989-6xjp2", "namespace_name"=>"default", "pod_id"=>"037e0276-650f-460f-85cb-095ed4f65cd7", "labels"=>{"pod-template-hash"=>"6f945d7989", "stdout"=>"stdout-node"}, "host"=>"worker2", "container_name"=>"stdout", "docker_id"=>"a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10", "container_hash"=>"sha256:aff389fbc4cac45f0ca6de06328e7d51f1d887306a9c278d4349f61e281ac562", "container_image"=>"docker.io/stdout/node:latest"}}]
[2] kube.var.log.containers.stdout-node-6f945d7989-6xjp2_default_stdout-a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10.log: [[1730388117.989854900, {}], {"time"=>"2024-10-31T15:21:57.9898549Z", "stream"=>"stdout", "_p"=>"F", "log"=>"2024-10-31T15:21:57.989Z warn : Log Hello World", "kubernetes"=>{"pod_name"=>"stdout-node-6f945d7989-6xjp2", "namespace_name"=>"default", "pod_id"=>"037e0276-650f-460f-85cb-095ed4f65cd7", "labels"=>{"pod-template-hash"=>"6f945d7989", "stdout"=>"stdout-node"}, "host"=>"worker2", "container_name"=>"stdout", "docker_id"=>"a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10", "container_hash"=>"sha256:aff389fbc4cac45f0ca6de06328e7d51f1d887306a9c278d4349f61e281ac562", "container_image"=>"docker.io/stdout/node:latest"}}]
[3] kube.var.log.containers.stdout-node-6f945d7989-6xjp2_default_stdout-a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10.log: [[1730388117.989863650, {}], {"time"=>"2024-10-31T15:21:57.98986365Z", "stream"=>"stdout", "_p"=>"F", "log"=>"2024-10-31T15:21:57.989Z error : Log Hello World", "kubernetes"=>{"pod_name"=>"stdout-node-6f945d7989-6xjp2", "namespace_name"=>"default", "pod_id"=>"037e0276-650f-460f-85cb-095ed4f65cd7", "labels"=>{"pod-template-hash"=>"6f945d7989", "stdout"=>"stdout-node"}, "host"=>"worker2", "container_name"=>"stdout", "docker_id"=>"a9b9155dd52d8338234bbbf37ccc057d72d7d4731044068a9beaaa2aeeba4f10", "container_hash"=>"sha256:aff389fbc4cac45f0ca6de06328e7d51f1d887306a9c278d4349f61e281ac562", "container_image"=>"docker.io/stdout/node:latest"}}]

 

 

fluent-bit를 설치하고 간단히 stdout 을 통해 테스트가 되는 것을 확인하였다.

OpenSearch 연동은 아래 링크 참조

2024.11.03 - [Develop/k8s] - OpenSearch, Dashboard 설치 및 Fluent-Bit OpenSeach 연동

반응형
반응형

 

kubernetes-dashboard 는 기본적으로 localhost 에서 https 를 권장하지만 Ingress 를 적용하여 접속할 수도 있다.

kubernetes-dashboard-kong-proxy를 기준으로 https ingress 접속하는 방법이다.

 

 

1. 인증서 생성

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=dashboard.wky.kr/O=Kubernetes"
또는
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=dashboard.wky.kr/O=Kubernetes" -addext "subjectAltName = DNS:dashboard.wky.kr"

 

 

2. secret 생성

kubectl create secret tls tls-dashboard --key tls.key --cert tls.crt -n kubernetes-dashboard

 

 

3. Ingress 생성 및 적용

# vi ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
spec:
  ingressClassName: nginx
  rules:
  - host: dashboard.wky.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard-kong-proxy
            port:
              number: 443
  tls:
  - hosts:
    - dashboard.wky.kr
    secretName: tls-dashboard
 
 # 적용
 kubectl apply -f ingress.yaml -n kubernetes-dashboard

 

 

4. 접속할 pc 의 hosts에 등록

vi /etc/hosts

172.1.1.1 dashboard.wky.kr

 

 

5. 확인

 

 

기타. ssl-passthrough

ssl-passthrough 를 적용하기 위해선 deployment에 --enable-ssl-passthrough 플래그를 추가한다.

kubectl edit deploy -n ingress-nginx ingress-nginx-controller

...
spec:
  containers:
  - args:
    - /nginx-ingress-controller
    - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
    - --election-id=ingress-nginx-leader
    - --controller-class=k8s.io/ingress-nginx
    - --ingress-class=nginx
    - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
    - --validating-webhook=:8443
    - --validating-webhook-certificate=/usr/local/certificates/cert
    - --validating-webhook-key=/usr/local/certificates/key
    - --enable-ssl-passthrough=true
...

 

ingress 설정

# vi ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /dash(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: kubernetes-dashboard-kong-proxy
            port:
              number: 443
 
 # 적용
 kubectl apply -f ingress.yaml -n kubernetes-dashboard

 

확인

반응형
반응형

 

k8s 인증서가 갱신되더라도 전에 사용하고 있던 config파일 내에 client-certificate-data 항목이 만료가 되지 않았으면,

그대로 정상동작하며, 해당 데이터에 대한 만료일자를 확인하는 방법이다.

 

root@master:~/tmp $ cat ~/.kube/config # client-certificate-data 값 확인
root@master:~/tmp $ echo "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tL~~~~~" | base64 --decode > client.crt
root@master:~/tmp $ ls
client.crt
root@master:~/tmp $ openssl x509 -in client.crt -noout -enddate
notAfter=Apr  7 13:49:20 2025 GMT

 

 

반응형

+ Recent posts