레이블이 proxy인 게시물을 표시합니다. 모든 게시물 표시
레이블이 proxy인 게시물을 표시합니다. 모든 게시물 표시

install mysql8 in rocky8

# rocky8 에서 mysql8.0 설치하기 위해선 다음과 같이 외부 저장소로 부터 설치해야 했다.
# 참고로 프록시가 필요한 경우 sudo 실행시 -E 로 proxy 설정 유지가 필요하다.
(프록시설정) sudo -E yum -y install https://dev.mysql.com/get/mysql80-community-release-el8-9.noarch.rpm

# 혹시나 잘못되면 다시 지우고 설치하자!!!(요거 몰라서 삽질)
sudo yum erase -y mysql80-community-release-el8-9.noarch

# mysql80 저장소가 보인다.
yum repolist enabled | grep mysql.*-community

# 기존 mysql 모듈은 비활성화 처리해야 mysql-community-8.0 패키지를 사용할 수 있다.
sudo yum module reset -y mysql
sudo yum module disable -y mysql

# 패지키 확인, 버전이 8.0으로 보인다.
sudo yum info mysql-community-devel mysql-community-server

# 이제 설치하면 된다.
(프록시설정) sudo -E yum install -y mysql-community-devel mysql-community-server

#####

# ansible 사용시
- block
  - name: "Install MySQL8 remote repository for Rocky 8"
    yum:
      # redirect url 사용시 에러 발생
      #name: "https://dev.mysql.com/get/mysql80-community-release-el8-9.noarch.rpm"
      name: "https://repo.mysql.com/mysql80-community-release-el8-9.noarch.rpm"
      state: installed
      sslverify: false
      disable_gpg_check: true
      update_cache: true
    when: ansible_distribution == "Rocky" and ansible_distribution_major_version == "8"

  - name: "Install MySQL8 devel package for Rocky 8"
    yum:
      name: mysql-community-devel
      state: installed
    when: ansible_distribution == "Rocky" and ansible_distribution_major_version == "8"

  - name: "Install MySQL8 server package for Rocky 8"
    yum:
      name: mysql-community-server
      state: installed
    when: ansible_distribution == "Rocky" and ansible_distribution_major_version == "8"

  become: true
  environment: "{{ my_proxy }}"

install yarn in ubuntu

# ubuntu(Ubuntu 22.04.2 LTS) 에서 yarn 실행을 하면 다음과 같은 에러가 발생한다.
00h00m00s 0/0: : ERROR: There are no scenarios; must have at least one.

# yarn 명령어의 위치를 보면 기본 명령어 위치에 있다.
which yarn
/usr/bin/yarn

# ubuntu 의 기본적으로 설치된 yarn 으로 scenario testing 툴이다.

# cmdtest 패키지를 삭제해야 한다.
sudo apt remove --autoremove cmdtest

# 참고로 다음과 같이 별도로 autoremove 로 사용하지 않는 패키지들을 삭제해도 된다.
sudo apt remove cmdtest
sudo apt autoremove

# 이제 npm 을 먼저 설치
# 참고로 apt install yarn 로 설치하면 다시 scenario testing 툴이 설치되지 주의
sudo apt install npm

# npm 으로 yarn 설치
sudo npm install -g yarn

# yarn 확인
which yarn
/usr/local/bin/yarn

# yarn 버전 확인
yarn --version
1.22.1

#####

# yarn install 연결 에러 발생함
info There appears to be trouble with your network connection. Retrying..

# 혹시 프록시 설정문제인지 해서 지워봤지만 안됨
yarn config set proxy ''
yarn config set https-proxy ''

# verbose 로 보면 private registry를 사용하고 있었다.
yarn install --verbose
verbose 0.113484 Performing "GET" request to "https://npm.ysoftman.in/axios"

# registry 확인 
yarn config get registry

# registry 설정 지우면 된다.
yarn config set registry ''

echo reverse proxy ingress localhost 404 error

/*
echo golang web framework 의 proxy 사용시 upstream 을 ingress domain 을 사용하면 404 not found 응답 이슈가 발생했다.

echo proxy 사용 예시 참고
https://echo.labstack.com/cookbook/reverse-proxy/

같은 localhost 로 업스트림 설정하면 문제가 없다.
http://localhost:8080 -> http://localhost:8081 (upstream local)

ingress domain 으로 업스트림을 설정하면 404 응답을 받는다.
http://localhost:8080 -> http://ysoftman.dev:8081 (upstream ingress)
404 Not Found

nginx pod 에 로그를 보면 다음과 같은 메시지가 기록된다.
호스트가 ysoftman.dev 로 되어야 할것 같은데, localhost 로 파악돼 pod 까지 요청이 전달되지 않는다.
Skipping metric for host not being served" host="localhost"

해결 방법
프록시 설정전 다음과 같이 핸들러를 등록하고 request host 를 ysoftman.dev 로 설정하면 ysoftman.dev 로 부터 200 OK 응답을 받는다.
*/

package main

import (
"net/http"
"net/url"

// ModifyResponse 사용을 위해선 echo v4 가 필요
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)

func main() {
url, _ := url.Parse("http://ysoftman.dev:8081")
e := echo.New()
g := e.Group("/test")

// 프록시 설정 전 request host 를 upstream host 로 변경
g.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Request().Host = url.Host
return next(c)
}
})

// set proxy upstream
proxyTargets := []*middleware.ProxyTarget{
{
URL: url,
},
}
g.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
Balancer: middleware.NewRoundRobinBalancer(proxyTargets),
ModifyResponse: func(resp *http.Response) error {
return nil
},
}))
}

docker pull forbidden 해결하기

# private registry 를 사용하는데 docker pull 하면, 다음과 같은 에러가 발생한다.
docker pull ysoftman.test.com/drone/drone:2
Error response from daemon: Get https://ysoftman.test.com/: Forbidden

# docker login 을 해도 forbidden 에러가 발생한다.
sudo docker login -u "ysoftman" -p "password" ysoftman.test.com

# docker daemon 정보를 보면 프록시가 설정되어 있고,
# ysoftman.test.com 이 프록시를 사용해 접근이 안되고 있었다.
docker system info | grep -i proxy
HTTP Proxy: http://ysoftman.proxy.test
HTTPS Proxy: http://ysoftman.proxy.test
No Proxy: localhost,127.0.0.1,aaa

# 프록시를 사용하지 않도록 http-proxy 파일을 수정한다.
sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
No Proxy: localhost,127.0.0.1,aaa,ysoftman.test.com

# 변경된 설정 파일을 reload 하기 위해서 daemon-reload 을 실행해야 한다.
sudo systemctl daemon-reload

# docker daemon(service) 재시작
sudo systemctl restart docker

# 이제 docker daemon 정보를 보면 no proxy 에 추가된 것을 확인할 수 있고
# docker pull ysoftman.test.com/drone/drone:2 도 잘된다.

docker daemon http_proxy 설정

# 사내 서버에서 aws ECR(elastic Container Registry)에 푸시 하기 위해 
# docker login 을 해야 하는데, 다음과 같이 환경 변수 설정하고
export HTTP_PROXY="http://프록시서버:1111"

# docker login 하면
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin xxx.ecr.ap-northeast-2.amazonaws.com

# 다음과 같이 docker daemon 에서 타임 아웃이 발생한다.
Error response from daemon: Get https://xxx.ecr.ap-northeast-2.amazonaws.com/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers


# 찾아보니 docker daemon 용 http-proxy.conf 을 사용해야 한다.
# docker daemon http-proxy 파일 생성
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://프록시서버:1111"
Environment="HTTPS_PROXY=http://프록시서버:1111"
Environment="NO_PROXY=localhost,127.0.0.1,127.0.0.0/8,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,.google.com,.naver.com,.daum.net"

# 리로딩 및 재시작
sudo systemctl daemon-reload && sudo systemctl restart docker

# http proxy 설정 확인
sudo systemctl show --property=Environment docker

# 재시작후 sudo 없이 docker 실행하기 위해 docker.sock 소유자 변경
sudo chown -R ysoftman:ysoftman /var/run/docker.sock

# 이제 다시 docker login 하면 성공~
Login Succeeded

drone ci 사용하기

# golang 으로 만들고 docker 환경으로 실행되는 drone ci 를 사용해보자.

# 우선 로컬에서 테스트하기 때문에 
# (reverse proxy 로 ngrok 도메인 -> localhost 로 터널링 해주는) ngrok 설치
brew install ngrok

# http://fe9b41d98488.ngrok.io -> http://localhost:80 포워딩을 위해 실행
# 참고 https (tls) 터널링은 유료 버전만 가능하고, 그외 동시접속 제한이 있다.
ngrok http 80

# github oauth 로 drone 앱(서버)를 등록
# github -> settings -> developers -> oauth apps 에서 신규 생성한다.
# homepage url : http://dd441e3e9f16.ngrok.io
# callback url : http://dd441e3e9f16.ngrok.io/login

# oauth app 생성후
# client -> DRONE_GITHUB_CLIENT_ID
# client secret -> DRONE_GITHUB_CLIENT_SECRET 로 사용한다.
# generate a new client secret(생성후 한번 볼 수 있어 복붙해둬야 한다) -> DRONE_GITHUB_CLIENT_SECRET 값으로 사용

# drone <-> runner 간 RPC 통신을 위한 secret 생성 -> DRONE_RPC_SECRET 값으로 사용
openssl rand -hex 16                         
d087c94b8155367b1982238df930c2f2

# drone 도커 이미지 다운로드
docker pull drone/drone:1

# 실행
# github enterprise 는 깃헙 서버 환경 변수 설정 필요
# --env=DRONE_GITHUB_SERVER=https://github.ysoftman.com \
# 볼륨 연결로 /data/database.sqlite -> 호스트의 /var/lib/drone/database.sqlite 로 저장
docker run \
  --volume=/var/lib/drone:/data \
  --env=DRONE_DATABASE_DRIVER=sqlite3 \
  --env=DRONE_DATABASE_DATASOURCE=/data/database.sqlite \
  --env=DRONE_GITHUB_CLIENT_ID=깃헙_클라이언트_id \
  --env=DRONE_GITHUB_CLIENT_SECRET=깃헙_클라이언트_secret \
  --env=DRONE_RPC_SECRET=d087c94b8155367b1982238df930c2f2 \
  --env=DRONE_SERVER_HOST=127.0.0.1 \
  --env=DRONE_SERVER_PROTO=http \
  --env=DRONE_WEBHOOK_ENDPOINT=http://dd441e3e9f16.ngrok.io/hook \
  --env=DRONE_WEBHOOK_SECRET=d087c94b8155367b1982238df930c2f2 \
  --env=DRONE_REPOSITORY_FILTER=ysoftman,bill \
  --publish=80:80 \
  --publish=443:443 \
  --restart=always \
  --detach=true \
  --name=drone \
  drone/drone:1

# 이제 다음 url 로 github authorize 하면 깃헙으로 로그인상태로 drone ci 를 사용할 수 있다.
http://dd441e3e9f16.ngrok.io

# DRONE_REPOSITORY_FILTER 으로 특정 저장소에만 drone과 연결 할 수 있다.
# 설정 변경 후 사용자별로 로그아웃 후 다시 로그인 해야 반영된다.

#####

# 상황에 맞는 여러 runner(러너)가 있다.
# docker(임시 컨테이너를 생성해 실행할때 사용) 러너 설치
docker pull drone/drone-runner-docker:1
docker run -d \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e DRONE_RPC_PROTO=http \
  -e DRONE_RPC_HOST=dd441e3e9f16.ngrok.io \
  -e DRONE_RPC_SECRET=d087c94b8155367b1982238df930c2f \
  -e DRONE_RUNNER_CAPACITY=2 \
  -e DRONE_RUNNER_NAME=${HOSTNAME} \
  -e DRONE_DEBUG=true \
  -e DRONE_TRACE=true \
  -p 3000:3000 \
  --restart always \
  --name runner \
  drone/drone-runner-docker:1

# exec(docker 와 같은 고립된 환경이 아닌 drone 서버 장비에서 쉘 환경에서 명령을 실행할 때 사용) 러너를 설치
curl --proxy "필요한 경우 프록시 설정" -L https://github.com/drone-runners/drone-runner-exec/releases/latest/download/drone_runner_exec_linux_amd64.tar.gz | tar zx
sudo install -t /usr/local/bin drone-runner-exec
mkdir -p /home/ysoftman/.drone-runner-exec
touch /home/ysoftman/.drone-runner-exec/config
cat > /etc/drone-runner-exec/config << eof
DRONE_RPC_PROTO=http
DRONE_RPC_HOST=dd441e3e9f16.ngrok.io
DRONE_RPC_SECRET=d087c94b8155367b1982238df930c2f
DRONE_LOG_FILE=/home/ysoftman/.drone-runner-exec/log.txt
eof
drone-runner-exec service install
drone-runner-exec service start

# drone-runner-exec 서비스 상태 확인
systemctl status drone-runner-exec.service

# docker 환경 변수 확인
docker inspect -f "{{.Config.Env}}" drone  | tr " " "\n"


# ssh(ssh 로 서버에 접속해 명령을 실행하는 용도) 러너 설치
docker pull drone/drone-runner-ssh
docker run -d \
  -e DRONE_RPC_PROTO=http \
  -e DRONE_RPC_HOST=dd441e3e9f16.ngrok.io \
  -e DRONE_RPC_SECRET=d087c94b8155367b1982238df930c2f \
  -p 3000:3000 \
  --restart always \
  --name runner \
  drone/drone-runner-ssh

# 루트 경로에 .drone.yml 를 작성한다.
# 파일명은 drone ci settings 에서 변경 가능하다.
---
kind: pipeline
type: exec
name: default

platform:
  os: linux
  arch: amd64

trigger:
  event:
    - push
steps:
  - name: 작업1
    commands:
      - echo hello world1
  - name: 작업2
    commands:
      - echo hello world2
  - name: 슬랙 알림
    # environment:
    #   noti_msg: "Branch: ${DRONE_BRANCH}\nAuthor: ${DRONE_COMMIT_AUTHOR}\nLink: ${DRONE_COMMIT_LINK}"
    #   build_status: "✅ build ${DRONE_BUILD_NUMBER} succeeded. Good job."
    commands:
      - echo "파이프 종료"
      - export HTTP_PROXY="http://프록시서버"
      - export noti_msg="Branch ${DRONE_BRANCH}\nAuthor ${DRONE_COMMIT_AUTHOR}\nLink ${DRONE_COMMIT_LINK}"
      - export build_status="✅ build ${DRONE_BUILD_NUMBER} succeeded. Good job."
      - echo $DRONE_BUILD_STATUS
      - if [[ $DRONE_BUILD_STATUS == "failure" ]]; then build_status="❌ build ${DRONE_BUILD_NUMBER} failed. Fix me please."; fi
      - |
        curl https://hooks.slack.com/services/..... -d "payload={\"channel\": \"#billtest\", \"text\": \"파이프 라인 시작\n$noti_msg\n$build_status\"}"
# ---
# kind: pipeline
# type: ssh
# name: default
# # 접속할 대상 서버
# server:
#   host: ysoftman-server.com
#   user: deploy
#   password:
#     from_secret: password
# steps:
#   - name: 작업1
#     commands:
#       - echo hello world1
#   - name: 작업2
#     commands:
#       - echo hello world2
# ---
# kind: pipeline
# type: docker
# name: slack notification
# # 사내환경등에서 외부 접속이 안되는 경우 프록시 환경 변수 설정
# environment:
#  HTTP_PROXY: "http://프록시주소"
#  HTTPS_PROXY: "http://프록시주소"
# steps:
#   - name: 슬랙 알림
#     # 사내환경등에서 외부 이미지 다운로드가 안되는 경우 알맞게 변경
#     image: plugins/slack
#     settings:
#       # https://my.slack.com/services/new/incoming-webhook 참고
#       webhook: https://hooks.slack.com/services/.....
#       channel: ysoftman-test
#       template: >
#         {{#success build.status}}
#           build {{build.number}} succeeded. Good job.
#         {{else}}
#           build {{build.number}} failed. Fix me please.
#         {{/success}}
#         Branch: {{ build.branch }}
#         Author: {{ build.author }}
#         Link: {{ build.link }}

# 이제 drone DRONE_WEBHOOK_ENDPOINT 변수로 설정된 url 을
# github 저장소 webhook url 을 추가해 push 되면 drone 에 알리도록 한다.
http://dd441e3e9f16.ngrok.io/hook

# 참고로 위의 HTTP_PROXY 와 같은 환경변수를 사용할때 
# ${HTTP_PROXY} 는 안되고 {} 를 제거한 $HTTP_PROXY 로 사용해야 한다.

#####

# drone cli 툴 사용 https://docs.drone.io/cli/install/
# 설치
brew install drone-cli

# aaaaabbbbb11111 는 drone > User Settings > token 로 확인
# 접속할 drone 서버 환경 변수 설정
export DRONE_SERVER=http://dd441e3e9f16.ngrok.io
export DRONE_TOKEN=aaaaabbbbb11111

# 접속 여부 확인
drone info

# .drone.yml 작업 수행(커밋 전에 미리 로컬에서 테스트할 수 있다.)
# drone exec 현재 type: docker 만 실행된다.
# .drone.yml 을 다음과 같이 만들고
kind: pipeline
type: docker
name: default

steps:
- name: build
  image: golang:1.13
  commands:
  - echo "aaa"

# 실행
# .drone.yml syntax 체크등에 활용할 수 있다.
drone exec

로컬에서 k8s redis cluster 접속

# k8s 에 redis cluster 를 구성하였다.
# redis 노드1개는 1개의 pod 로 구성되고, 이 pod 를 서비스로 묶었다.

# 다음과 클라이언트가 k8s 안의 pod(redis-cluster-0) 라면 접속이 잘된다.
kubectl --namespace redis exec -it redis-cluster-0 -- redis-cli -h {레디스 노드 중 하나} -p 6379 -c

# 실제 서비스 서버도 k8s 배포되어 운영시는 문제가 없지만
# 개발시에는 로컬에서 k8s redis 에 접근이 필요하다.
# 그래서 redis 의 k8s service 에 nodeport (32000) 설정하고 
# k8s nodeIP:nodeport 로 접속을 시도 하였다.
redis-cli -h {k8s 노드 중 하나} -p 32000 -c
# 접속은 되지만 set 수행시 연결되지 않고,
set aaa bbb
# 이미 저장된 값을 get 수행하면 moved 로 
# redis pod 로 redirect 시도하고 연결되지 않는다.
get aaa
moved xxxx

# 로컬에서 redis set,get 등 수행시 해당 값을 redis node(slot)으로 분배를 시도하고
# 결국 redis-cluster 의 pod(redis node) ip 에 접근할 수 밖에 없다.

# 해결 방법은 redis-cluster 를 프록시 해주는 redis-cluster-proxy 프로그램을
# k8s service(+pod)에 두고, 이 redis-cluster-proxy 로 요청을 하도록 한다.

# 먼저 redis-cluster-proxy 도커 이미지를 생성한다.
# os 버전이 낮아 gcc 버전이 낮으면 빌드 에러가 발생하니 최신 os 기반에서 빌드하자.
# 자세한 내용은 dockerfile 참고

# 이미 빌드된 redis-cluster-proxy 도커 이미지 사용시 참고


# 이제 redis-cluster-proxy 를 k8s service(+pod)로 다음과 같이 구성한다.
# redis-cluster-proxy.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-cluster-proxy
  labels:
    app: redis-cluster-proxy
spec:
  containers:
    - name: redis-cluster-proxy
      image: ysoftman/redis-cluster-proxy:latest
      imagePullPolicy: Always
      command:
        ["/redis-cluster-proxy/src/redis-cluster-proxy", "10.123.123.123:6379"]
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster-proxy
  labels:
    app: redis-cluster-proxy
spec:
  # type: ClusterIP
  type: NodePort
  ports:
    - port: 7777
      targetPort: 7777
      nodePort: 30777 # The range of valid ports is 30000-32767
      name: redis-cluster-proxy
  selector:
    app: redis-cluster-proxy

# k8s service(+pod) 반영
kubectl apply -f redis-cluster-proxy.yaml --namespace redis

# 다음과 같은 요청 흐름이 된다.
로컬 redis-cli k8s 노드 중 하나:30777 --> redis-cluster-proxy(service) --> redis-cluster-proxy(pod):7777 --> redis cluster nodes(pods):6379

# 이제 로컬 개발시에는 redis-cluster-proxy 를 통해 k8s redis 를 사용할 수 있다.
redis-cli -h {k8s 노드 중 하나} -p 30777 -c


#####


# helm 으로 외부에서 접근 가능한 redis-cluster 으로 구성할 경우
# 다음과 같이 실행하면 service 3개에 각각 redis pod 1개를 띄우고, 
# 서비스별 external ip 를 생성한다.(시간이 좀 걸린다.)
helm install redis-cluster bitnami/redis-cluster \
--namespace redis-cluster \
--set cluster.node=3 \
--set cluster.externalAccess.enabled=true

# 이후 helm upgrade 설치 가이드 명령 참고해서 
helm upgrade redis-cluster bitnami/redis-cluster \
--namespace redis-cluster \
--set cluster.node=3 \
--set cluster.externalAccess.enabled=true \
--set cluster.externalAccess.service.type=LoadBalancer \
--set "cluster.externalAccess.service.loadBalancerIP[0]=10.10.10.1,cluster.externalAccess.service.loadBalancerIP[1]=10.10.10.2,cluster.externalAccess.service.loadBalancerIP[2]=10.10.10.3"


# 참고


vue local devserver proxy

# 예시
# 현재 로컬 서버 http://localhost:8080
# 요청 서버 http://my.ysoftman.com:443

# 로컬에서 vue 개발시, 도메인이 다른 호스트 요청시 발생하는
# cors(Cross-origin resource sharing) 에러 해결을 위해
# vue.config.js (webpack) proxy 를 설정한다.
 
module.exports = {
  // 로컬 개발시(이 파일 수정시 npm run serve 로 다시 시작해야함)
  devServer: {
    https: true,
    // /api 로 시작하는 경로 요청을 target 으로 요청
    proxy: {
      '^/api': {
        target: 'https://my.ysoftman.com:443',
        changeOrigin: true,
      },
    disableHostCheck: true,
  },
};

# 위와 같이 프록시 설정하면, cors 이슈도 없고, 쿠키등의 헤더도 잘 전달된다.

# 주의사항
# xmlhttprequest, axios 등으로 요청 호스트명을 빼서 로컬 호스트로 요청해야 한다.
# 그래야 위 (로컬서버에 대한) 프록시 처리가 된다.


#####


# 만약 호스트명이 필요한 실제 서비스 환경과 로컬 develop 개발 환경 구분이 필요한 경우
# host 변수을 두고 다음과 같이 process.env.NODE_ENV 에 따라 '' 로 설정해 처리하자.

let host = "http://my.ysoftman.com:443"
if (process.env.NODE_ENV != null && process.env.NODE_ENV == 'development')
{
  return '';
}


go mod 캐시 삭제

# 사내 네트워크에서
# git 버전 변경이나 저장소 변경 등으로 사용중이 go.mod 의 변화가 있을때
# 빌드시 다음과 같은 패키지를 가져오지 못하는 403 에러가 발생한다.
go: github.aaa.com/ysoftman/sample@v0.1: unrecognized import path "github.aaa.com/ysoftman/sample" (https fetch: Get https://github.ysoftman.com/ysoftman/sample?go-get=1: Forbidden)

# proxy 환경 변수 중 no_proxy 에 추가한다.
export no_proxy=github.aaa.com,github.bbb.com

# 참고로 패키지 경로를 찾지 못하는 경우
https://github.com/golang/go/issues/27238#issuecomment-432793244
# mod 로 다운로드 받은 모든 패키지 삭제
go clean -modcache

# 테스트 결과물 캐시 삭제시
go clean -testcache

# 빌드 결과물 캐시 삭제시
go clean -cache

jenkins github credential 실패시 확인사항

[문제]
github.aaa.com 에서 github.bbb.com 으로 마이그레이션
github.bbb.com 계정으로 developer settings -> personal access token 을 생성
jenkins -> credentials -> ysoftman bbb secrect key (personal access token 를 사용한다.) 생성
jenkins -> 환경설정 -> github 에 다음과 같이 설정하고
API URL : https://github.bbb.com/api/v3
Credentials : ysoftman bbb secrect key
Test connection 실행하면 다음과 같이 실패한다.
Failed to validate the account

[원인 및 해결]
/var/jenkins/jenkins.log 로그를 보면 403(bad request)로 실패한다.
그런데 jenkins 서버 터미널로 테스트 하면 github.bbb.com 에 잘 접속된다.
curl http://ysoftman:토큰@github.bbb.com/api/v3

원인은 jenkins 에 설정된 프록시 서버 문제로
jenkins -> plugin manager -> 고급 -> http 프록시 설정에 no proxy host 에 github.bbb.com 추가하면 접속 된다.
jenkins job 까지 프록시 설정을 반영하기 위해선 http://젠킨스주소/restart 로 재시작해야 한다.

[추가로]
tomcat 상으로 jenkins 가 구동되는 경우, jenkins 만 재시작하면 안된다.
tomcat 데몬이 올라갈때의 no_proxy 설정이 유지되기 때문에
bash 상에서 다음과 같이 no_proxy 설정 후 tomcat 을 재시작해야 한다.
export no_proxy=github.aaa.com,github.bbb.com

vscode 원격 개발

# vscode 1.35 부터 remote develop extension 을 설치해
# ssh, docker container, wsl 의 원격 개발 환경을 이용 할 수 있다.
# 참고로 아이콘도 좀 심플하게(예쁘게) 변경됐다.~ㅎ

# 원격 접속은 원격 서버의 ${HOME}/.vscode-server 프로그램을 설치하고 vscode-server 가 실행돼 원격으로 접속하게 된다.
# vscode-server 는 wget 로 다운로드를 하게 되는데
# 참고로 사내망이라면 http_proxy 환경 변수를 설정 해줘야 한다.

# docker container 가 이미 떠있는 경우
remote-containers : attach to running container
-> 현재 떠있는 컨테이너 선택 -> 새 vscode 창이 오픈

# 새 vscode 가 생성되면 컨테이너의 소스 파일을 열어 볼 수 있고,
# vscode 터미널에서 빌드 커맨드 등을 실행할 수 있는 상태가 된다.

# remote ssh 는 ~/.ssh/config 와 ~/.ssh/authorized_keys 사용한다.
# kerberos 인증 환경에서도 접속할 수 있다.
# settings.json 설정에 다음을 추가하면 로그인 터미널 상태를 표시해준다.
"remote.SSH.showLoginTerminal": true

# 로그인 터미널에 다음과 같은 에러가 발생하는 경우
channel 2: open failed: administratively prohibited: open failed

# 대상 호스트 서버의 /etc/ssh/sshd_config 에 tcp 포워딩 가능하도록 설정한다.
AllowTcpForwarding yes

# 그리고 sshd 서버를 재시작한다.
sudo systemctl restart sshd

# 기타 접속 이슈 해결방법 참고
https://code.visualstudio.com/docs/remote/troubleshooting#_troubleshooting-hanging-or-failing-connections

# remote develop 기능은 vscode live share(로컬 코드를 공유)와 비슷하지만
# 원격 장비의 코드를 vscode 로 볼 수 있어 좋은것 같다.

envoy proxy 사용하기

# envoy 는 프로시 서버로 요청을 원하는 곳으로 라우팅(포워딩)해준다.
# https://github.com/envoyproxy/envoy


##########


# mac 에서 envoy build
# brew llvm 버전 https://formulae.brew.sh/formula/llvm
brew install coreutils wget cmake libtool go bazel automake ninja llvm@7 autoconf

# 업그레이드 에러가 나오는 패키지들에 대해선 업그레이드를 수행 
brew upgrade coreutils wget cmake go ninja

# evnoy 소스 클론
git clone https://github.com/envoyproxy/envoy

# bazel 로 빌드
# worksapce 는 현재 envoy 소스 루트 디렉토리이고
# workspace 에서 상대위치 //source/exe 에 BUILD 파일이 있고
# BUILD 파일내에서 envoy-static 타겟으로 빌드
bazel build //source/exe:envoy-static

# bazel 빌드중 libz.a 실패해서 포기ㅠ


##########


# docker envoy 사용하기
# envoy 도커 이미지 받기
docker pull envoyproxy/envoy

# envoy 컨테이너 실행
# 디폴트로 9901 은 admin 접속하고, 10000 로 리슨하고 있다.
docker run --name envoy -p 9901:9901 -p 10000:10000 -dit envoyproxy/envoy

# envoy 컨테이너 삭제
docker rm -f envoy

# envoy 컨테이너 접속
docker exec -it envoy /bin/bash

# 디폴트 설정
cat /etc/envoy/envoy.yaml

# 10000 으로 요청하면 envoy 가 구글로 라우팅(포워딩) 한다.
http://127.0.0.1:10000/

# 이제 envoy.yaml 설정을 수정해 보자
# 참고로 docker envoy 이미지는 Ubuntu 버전이다.
# cat /etc/issue
# Ubuntu 16.04.6 LTS \n \l
# 최소한의 용량으로 vim 과 같을 툴은 기본적으로 설치되어 있지 않다.
# vim 을 설치하기 위해선 패키지 관리자 apt-get 을 업데이트하고 설치해야 한다.
# apt-get update && apt-get install -y vim
# vim 없으 아래명령으로 파일을 덮어 쓰자.
# daum.net 으로 라우팅을 변경해보자.
# admin 도 0.0.0.0 으로 모든 IP 에서의 접근을 허용하자.
cat > /etc/envoy/envoy.yaml << zzz
admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite: www.daum.net
                  cluster: service_daum
          http_filters:
          - name: envoy.router
  clusters:
  - name: service_daum
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_daum
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.daum.net
                port_value: 443
    tls_context:
      sni: www.daum.net
zzz


# 설정 파일을 수정 후 envoy 재시작한다.
# https://www.envoyproxy.io/docs/envoy/latest/operations/hot_restarter
# --restart-epoch 로 재시작을 할 수 있지만 프로세스를 중지(ctrl+c)하면 컨테이너가 종료된다.
# /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --restart-epoch 1 -l trace

# 그래서 변경된 설정파일 적용을 위해선 evnoy container 를 재시작한다.
docker stop envoy
docker start envoy

nginx upstream 404 응답 sleep 후 재시도하기

# nginx 를 reverse-proxy 로 사용하는 경우
# upstream 에서 404 응답을 주면 몇초후 다시 시도하는 방법
# 우선 sleep 및 location 이동등을 위해 nginx 빌드시 echo 모듈을 추가한다.

# echo 모듈
git clone https://github.com/openresty/echo-nginx-module.git
export ECHO_PWD=$(pwd)/echo-nginx-module

# nginx configure 수행 및 빌드 및 설치
./configure --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module --add-module=$ECHO_PWD
make
sudo make install


#####


# 이제 nginx.conf 를 다음과 같이 설정한다.
http {
... 생략 ...
    upstream ysoftman_web_server {
        server 127.0.0.1:55555;
        # bakcup : marks the server as a backup server. It will be passed requests when the primary servers are unavailable.
        server 127.0.0.1:55555 backup;
        server 127.0.0.1:55555 backup;
    }
    server {
... 생략 ...
        # /main 또는 /test 또는 /zzz 요청되는 경우
        location ~ ^/(main|test|zzz)$ {
            proxy_set_header Host $host;
            proxy_set_header Https-On $https;
            proxy_pass_request_headers  on;
            proxy_read_timeout     5s;
            proxy_connect_timeout  5s;
            # 업스트림서버의 응답이 에러(300 이상일 경우)인 경우 error_page 설정된 곳에서 처리
            proxy_intercept_errors on;
            # recursive_error_pages on;
            error_page 404 = /zzz_error_404;
            # 커넥션에러, 타임아웃, 502, 404 발생할때 backup 업스트림서버로 다시 요청
            proxy_next_upstream error timeout http_502 http_404;
            proxy_pass http://ysoftman_web_server/$1?$args;
            # echo_sleep 와 proxy_pass 는 각각의 핸들러를 가지고 있어
            # 둘을 같은 location 에 위치하면 충돌이 발생한다.
            # 왜냐면 nginx 는 location 에 하나의 핸들러만 허용하기 때문이다.
            # 업스트림은 처리되지 않고 3초 기다리고 클라이언트에 응답 준다.
            # echo_sleep 3;
        }
        location = /zzz_error_404 {
            echo_sleep 3;
            echo_location /retry_404;
        }
        location ~ ^/(retry_404)$ {
            proxy_pass http://ysoftman_web_server$request_uri;
            error_page 404 = /normal_error_404;
        }
        error_page  404              /normal_error_404;
        location = /normal_error_404 {

        }

... 생략 ...

}

# 우선 백엔드(업스트림서버)는 /zzz 가 404 응답을 주도록 설정되어 있다.
# 업스트림 404 응답시 sleep 후 재시도 흐름으로 진행된다.
1.클라이언트가 http://127.0.0.1:8080/zzz 로 요청
2. location ~ ^/(main|test|zzz)$ 에서 업스트림으로 요청, 이때 업스트이 404 에러를 주면 /zzz_error_404 로 핸들링하도록 설정해둔다.
3. 업스트림 404 에러 응답으로 /zzz_error_404 가 실행되고, echo_sleep 으로 3초 대기후 /retry_404 를 호출한다.
4. /retry_404 에서는 다시 업스트림 요청(proxy_pass)하게 되고, 이때 업스트림이 404 에러를 주면 끝낼 수 있도록 /normal_error_404 로 핸들링하도록 설정한다.
5. 다시 업스트림 404 에러를 받으면 /normal_error_404 에서 아무 처리하지 않고 클라이언트에게 404 응답을 준다.


#####


# 참고
# nginx 설치 및 위 내용 테스트 소스

# 백엔드 서버 소스

client ip 를 nginx 에서 apache 로 전달하기

# 다음과 같이 apache httpd 이전에 nginx 에거 사용자 요청을 받는 경우,
# apache httpd 에서의 remote ip 는 nginx ip 가 된다.
client(10.10.10.10) --> nginx (20.20.20.20) --> apache httpd (30.30.30.30)

# apache httpd  에서 client ip 를 파악하기 위해선 nginx.conf 에서 다음과 같이
# 프록시(apache httpd)에 전달시 헤더에 X-Real-IP 나 X-Forwarded-For 값을 설정한다.
# $proxy_add_x_forwarded_for 는 $remote_addr 가 포함된 클라인트 요청 헤더다.
vi nginx.conf
server{
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://30.30.30.30:PORT;
    }
}

# apache httpd 2.2 에선 mod_rpaf 를 설치하고
# rpaf 모듈을 사용하여 nginx 가 보낸 헤더를 사용할 수 있도록 다음과 같이 설정한다.
vi httpd.conf
LoadModule rpaf_module modules/mod_rpaf-2.0.so
<IfModule mod_rpaf.c>
    RPAFenable On
    RPAFsethostname On
    PAFheader X-Forwarded-For
    RPAFproxy_ips 20.20.20.20
</IfModule>

# apache httpd 2.4 부터는 RemoteIPHeader 를 제공하여 있어 다음과 같이 설정에 추가한다.
vi httpd.conf
LoadModule remoteip_module modules/mod_remoteip.so
<IfModule remoteip_module>
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 123.123.123.123
    RemoteIPTrustedProxy 10.0.0.0/8
</IfModule>

참고
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
https://chrismorris.org/passing-ip-from-nginx-to-apache/
https://github.com/y-ken/mod_rpaf
https://httpd.apache.org/docs/current/mod/mod_remoteip.html

centos6 gcc 4.8 이상 설치

centos 6.x 의 기본 gcc 버전은 4.4.x 다.
최근의 프로그램들은 gcc 4.8 이상에서 빌드되는 경우가 많은데 os 업그레이드 없이 gcc 버전을 업데이트 해보자.

# repo 추가
# 혹시 보안상의 이유로 proxy 가 필요하다면 proxy 설정을 export 한다.
# sudo 에서 export 된 proxy 설정을 사용하기 위해 -E 추가
sudo -E wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtools-2.repo

# 패키지 설치
sudo -E yum install centos-release-scl-rh
sudo -E yum install devtoolset-3-gcc devtoolset-3-gcc-c++

# gcc, g++ 위치
/opt/rh/devtoolset-3/root/usr/bin/

# devtoolset 활성화
# .bashrc 에 추가해서 사용하자.
source /opt/rh/devtoolset-3/enable