spring cloud config 사용시 사용자 이름, 패스워드를 입력한다


"java -jar config-server.jar --spring.cloud.config.server.git.username=knight76 --spring.cloud.config.server.git.password=1234"


아니면 프로퍼티(property) 설정을 추가한다.


spring.cloud.config.server.git.username=knight76

spring.cloud.config.server.git.password=1234




패스워드가 나타나는 게 꺼림직하다.

jasypt(com.github.ulisesbocchio:jasypt-spring-boot-starter) 라이브러리를 사용하면 암호화를 할수 있다.


gradle 설정에  jasypt(com.github.ulisesbocchio:jasypt-spring-boot-starter) 라이브러리를  추가한다.

dependencies {
implementation 'org.springframework.cloud:spring-cloud-config-server'
implementation 'org.springframework.cloud:spring-cloud-starter-config'
compile 'com.github.ulisesbocchio:jasypt-spring-boot-starter:2.1.2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}


application.properties에 


server.port=8080
jasypt.encryptor.bean=jasyptStringEncryptor

management.endpoint.env.enabled=true
management.endpoints.web.exposure.include=*

spring.cloud.config.server.bootstrap=true
spring.cloud.config.server.git.uri=https://github.com/knight76/spring-cloud-config-example
spring.cloud.config.server.git.timeout=5
spring.cloud.config.server.git.username=knight76
spring.cloud.config.server.git.password=123214



암호화에 사용되는 JasyptConfig 클래스를 추가한다. 


package com.github.knight76.config.configserver;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {

final static String KEY = "knight76";

final static String ALGORITHM = "PBEWithMD5AndDES";

@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(KEY);
config.setAlgorithm(ALGORITHM);
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}

}


 테스트 코드는 다음과 같다. 테스트 코드의 비밀번호를 사용한다. 

package com.github.knight76.config.configserver;

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ConfigServerApplicationTests {

@Test
public void test() {
StandardPBEStringEncryptor standardPBEStringEncryptor = new StandardPBEStringEncryptor();
standardPBEStringEncryptor.setAlgorithm(JasyptConfig.ALGORITHM);
standardPBEStringEncryptor.setPassword(JasyptConfig.KEY);

String enc = standardPBEStringEncryptor.encrypt("비밀번호");
System.out.println("enc = " + enc);

String des = standardPBEStringEncryptor.decrypt(enc);
System.out.println("des = " + des);
}
}



테스트 코드를 통해 얻은 비밀번호를 application.properties의 비밀번호로 설정한다. ENC(..비밀번호..)로 적용한다.


server.port=8080
jasypt.encryptor.bean=jasyptStringEncryptor

management.endpoint.env.enabled=true
management.endpoints.web.exposure.include=*

spring.cloud.config.server.bootstrap=true
spring.cloud.config.server.git.uri=https://github.com/knight76/spring-cloud-config-example
spring.cloud.config.server.git.timeout=5
spring.cloud.config.server.git.username=knight76
spring.cloud.config.server.git.password=ENC(암호문)


풀 예제 코드는 다음과 같다.

https://github.com/knight76/spring-cloud-config-example



이 방식 외에 RSA 비밀 키를 사용하는 방식이 있다. 


https://cloud.spring.io/spring-cloud-config/reference/html/


spring: cloud: config: server: git: uri: git@gitserver.com:team/repo1.git ignoreLocalSshSettings: true hostKey: someHostKey hostKeyAlgorithm: ssh-rsa privateKey: | -----BEGIN RSA PRIVATE KEY----- MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud 1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj 5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8 +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4 VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J 69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT 

-----END RSA PRIVATE KEY-----


Posted by '김용환'
,



nginx(tls 인증서)+webapp을 포함한 도커를 kubernetes에서 사용하려면 

k8s 443(ingress)-> 443(service) -> 443 (docker)로 적용되야 하는데.. 이는 처음부터 잘 작동되지 않는다. k8s ingress와 service에 tls인증서가 없고 docker 단에서 처리되야 하기에... 이슈가 있다.


만약 이를 동작하게 하려면 ssl paththough라는 기술을 사용해야 한다.



kubernetes (쿠버네티스) ssl passthrough 관련 정보


https://medium.com/ibm-cloud/how-to-enable-ssl-passthrough-in-ibm-cloud-private-d33e5d442d96


https://github.com/kubernetes/ingress-nginx/issues/803


https://www.thomas-zuehlke.de/2019/02/setup-kubernetes-ingress-with-ssl-passthrough/




Posted by '김용환'
,


helm 차트 삭제 (helm delete) 삭제하는 예시



$ helm ls --all --short $(kubectl config current-context) | xargs -L1 helm delete

삭제


$ helm ls --all $(kubectl config current-context)

NAME                  REVISION UPDATED                  STATUS  CHART                   APP VERSION NAMESPACE

google-production-context 25       Wed Sep 11 20:31:07 2019 DELETED prometheus 10.19.0      monitoring



$ helm del --purge  $(kubectl config current-context)

release "google-production-context" deleted


--purge를 해야 깔끔히 정리한다 .




helm 차트 추가하기(with 사설 저장소 추가)



$ helm repo add google-community http://charts.google.io

$ helm repo update


$ helm install --name $(kubectl config current-context) google-community/k8s-prometheus




Posted by '김용환'
,



맥북에서 도커 네트워크(brider)를 생성하는 예시이다. 


$ docker network create --driver=bridge mynet

1e322c39b6415e3d6b76bee009e8282d6e9e738e9b35930abc875c1cf20578fa

$ docker network ls | grep mynet

1e322c39b641        mynet                           bridge              local


정상적으로 드라이버가 생겼는지 확인한다.


$ ifconfig

(리눅스에서는 ip addr | grep br-)


bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500

options=63<RXCSUM,TXCSUM,TSO4,TSO6>

ether 4a:00:24:80:b7:01

Configuration:

id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0

maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200

root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0

ipfilter disabled flags 0x2

member: en1 flags=3<LEARNING,DISCOVER>

        ifmaxaddr 0 port 13 priority 0 path cost 0

member: en2 flags=3<LEARNING,DISCOVER>

        ifmaxaddr 0 port 14 priority 0 path cost 0

member: en3 flags=3<LEARNING,DISCOVER>

        ifmaxaddr 0 port 15 priority 0 path cost 0

member: en4 flags=3<LEARNING,DISCOVER>

        ifmaxaddr 0 port 16 priority 0 path cost 0

nd6 options=201<PERFORMNUD,DAD>

media: <unknown type>

status: inactive



생성된 네트워크(bridge)를 사용하는 컨테이너를 실행한다.


$ docker run -it -d --name container1 --net=mynet ubuntu:16.04 bash  



두 번 커맨드를 사용해 생성된 네트워크(bridge)를 사용할 수 있다.


$ docker run -it -d --name container2 ubuntu:16.04 bash           


$ docker network connect mynet container2




내부 ip를 확인해본다.


$  docker exec container1 ip addr

20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default

    link/ether 02:42:ac:19:00:02 brd ff:ff:ff:ff:ff:ff

    inet 172.25.0.2/16 brd 172.25.255.255 scope global eth0

       valid_lft forever preferred_lft forever

       

$  docker exec container2 ip addr 


(비슷하게 나온다)


Posted by '김용환'
,

공용 IP 얻기

Web service 2019. 9. 14. 16:28



PC에서 공용 Ip를 찾는 방법이다.


보통은 eth0을 찾기 위해 ifconfig 또는 ip address list를 실행하는데, 도커나 가상 네트워크 등을 설치/설정하면서 복잡해질 때가 있다.


브라우져에서 https://ifconfig.co 를 실행하거나 


curl https://ifconfig.co를 실행한다.

Posted by '김용환'
,


플랫 네트워크(flat network) - 비용, 유지 관리, 관리를 줄이기 위한 컴퓨터 네트워크 설계 방식으로서 장치를 별도의 스위치 대신 단일 스위치에 연결하여 컴퓨터 네트워크의 라우터와 스위치 개수를 줄이는 방식이다. 즉 중간 단계 없이 직접 통신할 수 있는 방식을 말한다. 따라서 계층적 네트워크(hierarchy network)와 달리 플랫 네트워크는 스위치를 사용해 물리적으로 분리되지 않는다

플랫 네트워크의 예로 도커의 브릿지(bridge)를 예로 들 수 있다.

도커의 브릿지는 컨테이너 간의 플랫 네트워크(flat network)를 생성하고 요청을 외부에 외부 연결로 전달한다.

Posted by '김용환'
,



kubernetes의 Service.spec.type의 기본값은 ClusterIP이다. 

clusterip는 iptables 기반이다.  k8s 서비스를 클러스터 내부 IP에 노출하고 클러스터 내에서만 서비스에 도달할 수 있게 한다. 


(참고 : kubernetes)





이외 3가지가 더 있다. 

Ingress를 사용하지 않으면 Nodeport를 사용한다. 

하지만 개인적으로 Ingress를 두는 것이 운영하는 데 훨씬 도움이 되는 것 같다. 


LoadBalancer는 LBaaS로 사용자가 로드 밸런서를 추가할 수 있는 형태이다.


아마존의 경우는 아래와 같이 사용할 수 있다. 

https://aws.amazon.com/ko/blogs/opensource/network-load-balancer-nginx-ingress-controller-eks/




https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md




실제 사용 예를 살펴본다. 아래 ingress-nginx에 잘 나와 있다. 

https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md


type이 LoadBalancer 타입일 경우에는 어떻게 설정되어 있는지 확인할 수 있다. 


aws L4 LB를 사용하려면 다음과 같이 사용한다. 

https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/service-l4.yaml

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  annotations:
    # Enable PROXY protocol
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
    # Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
    # NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
    # increased to '3600' to avoid any potential issues.
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: https

---



l7인 경우는 다음과 같이 설정한다. 

https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/service-l7.yaml


kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  annotations:
    # replace with the correct value of the generated certificate in the AWS console
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX"
    # the backend instances are HTTP
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
    # Map port 443
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
    # Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
    # NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
    # increased to '3600' to avoid any potential issues.
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: http

---






마지막으로 EnternalName은 CoreDNS에서 지원하는 CNAME 값이다. 







지금까지 설명한 내용은 다음 문서에 있다. 

https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types


  • ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType.
  • NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You’ll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
  • LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
  • ExternalName: Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record

    with its value. No proxying of any kind is set up.



Posted by '김용환'
,



(이미지만 참고) Refernece : https://www.youtube.com/watch?v=TFAASAfO_gg





외부 또는 중요한 내부 서버와 통신할 때 ACL을 뚫어서 통신할 때가 있다.


현재 kubernetes 클러스터의 서버(node)만 보고 ACL을 뚫으면 나중에 새로운 서버가 추가되고 새로운 장비에 실행된 pod에서는 막힌 부분 때문에 에러가 발생할 것이다.



특정 장비(node)에만 pod를 배포하면 이슈가 없을 것이다.



이에 대한 2가지 방법이 있다.


1. pod 적용


이 방식은 공식 문서에 있는 방식이다. 



https://kubernetes.io/docs/concepts/configuration/assign-pod-node/






2. deployment 적용




$ kubectl label nodes google-k8s-worker001 server=google-config

$ kubectl label nodes google-k8s-worker002 server=google-config



$ kubectl get nodes -l server=google-config
NAME               STATUS   ROLES   AGE   VERSION
google-k8s-worker001   Ready    node    14d   v1.11.5

google-k8s-worker002   Ready    node    14d   v1.11.5
 


apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: google-config
namespace: production
spec:
selector:
matchLabels:
app: google-config
replicas: 2
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 3
template:
metadata:
labels:
app: google-config
spec:
nodeSelector:
server: google-config

containers:
- name: google-config
image: dockerhub-url
imagePullPolicy: Always


테스트 방법은 다음과 같다. 

google-config를 1번 2번 장비에서만 실행되게 했다.


$ kubectl delete pod $(kubectl get pods | grep config | awk '{print $1}') 


삭제된 pod가 계속 1번 2번 장비에서 실행되는지 확인한다.




Posted by '김용환'
,

[docker] cmd와 entrypoint

docker 2019. 9. 10. 09:44



도커 컨테이너가 시작될 때 사용되는 커맨드로 CMD와 ENTRYPOINT가 있다. 



<CMD >

도커 컨테이너가 시작될 때 실행된다. 

CMD를 사용해야 ARG와 ENV를 쉽게 사용한다.

CMD ["Executable", "매개 변수"...] 
CMD의 매개 변수는 docker run에 사용된 매개변수로 덮어쓰인다




<ENTRYPOINT>

도커 컨테이너가 시작될 때 실행된다. 

CMD의 매개 변수는 docker run에 사용된 매개변수로 덮어쓰지 않는다. 즉 그대로 실행된다.



Posted by '김용환'
,

[docker] ENV와 ARG 비교

docker 2019. 9. 10. 09:40



코딩으로 따지면 컴파일 타임(compile-time), 런타임(run-time)처럼..

도커 파일에는 이에 해당하는 ARG(build-time)와 ENV(run-time)가 존재한다. 




<ARG>


표현식 : ${변수:+값}, ${변수:-값} 

빌드 시점에 사용한다

도커 파일에서 ARG 변수 혹은 ARG 변수=값 형태로 표현할 수 있다. 

docker build 커맨드에 --build-arg 옵션을 사용해 매개 변수를 전달하거나 덮어쓸 수 있다. 




<ENV>

표현식 : ${변수:+값}, ${변수:-값} 

런타임 환경변수이다

docker run 커맨드 --e 옵션을 활용해 매개 변수를 전달하거나 덮어쓸 수 있다.





개인적으로 ARG보다는 ENV를 사용해 docker run을 사용하는 편이다. 






Posted by '김용환'
,