Diatec FILCO 마제스터치 컨버터블2 사용법
마제스터치 컨버터블2 을 사용하고 있어서 기록으로 작성함. 현재 이 커보드는 단종되서 더 이상 생산되지 않음. 내가 가지고 있는 것은 저소음 적축임.
마제스터치 컨버터블2 을 사용하고 있어서 기록으로 작성함. 현재 이 커보드는 단종되서 더 이상 생산되지 않음. 내가 가지고 있는 것은 저소음 적축임.
레오폴드 FC750RBT PD 키보드를 사용하고 있어 메뉴얼을 캡쳐해 기록해 둠.
키크론 K3 White LED 를 사용하고 있어서 사용방법을 간단하게 정리함.
현재 개인적으로 Harbor 를 사용하고 있다. 별로 중요하지 않은 프로젝트여서 크게 신경쓰지 않는 저장소인데, 그래도 이래저래 테스트를 하는데 유용하다. Harbor 를 사용하다가 새로운 버전이 출시되어서 어떻게 업데이트를 했는지를 기록으로 남겨둔다.
Harbor 를 정지 시켜야 한다. Harbor 는 Docker-compose 기반으로 작동됨으로 docker-compose 명령어를 이용해서 다음과 같이 정지를 시켜줘야 한다.
1 |
]# docker-compose down |
혹시 잘못됐을때를 대비해 Backup 을 해준다. 디렉토리를 그냥 복사해주는 것으로 하면 된다.
1 |
]# mv /app/harbor /app/harbor_20241228 |
Docker 명령어를 이용해서 새로운 버전의 harbor 이미지를 다운로드 한다.
1 |
]# docker pull goharbor/prepare:v2.10.3 |
기존의 데이터베이스를 새로운 버전으로 Migration 을 해야 한다.
1 |
]# docker run -it --rm -v /:/hostfs goharbor/prepare:v2.10.3 migrate -i /app/harbor/harbor.yml |
데이터베이스 마이그레이션할 내용이 없으면 그냥 끝나게 된다.
새로운 버전의 Harbor 을 다운로드 하고 난후, install.sh, common.sh, prepare 파일을 기존 디렉토리에 복사해 준다.
1 2 3 |
]# mv harbor_2.10.3/install.sh . ]# mv harbor_2.10.3/common.sh . ]# mv harbor_2.10.3/prepare . |
이제 새로운 버전을 설치를 한다.
1 |
]# ./install.sh --with-trivy |
크게 어려운건 없다. 순서대로 했는데 중간에 문제가 되거나 하지 않았다. 업데이트를 한 후에 저장소를 사용하고 있는데, 기존 자료가 이상해지거나 되는 기능이 되지 않는 문제는 없었다.
유용한 Git 명령어 정리.
대부분 Git 설정은 명령어로 한다.
1 |
git config --global user.name "systemv" |
하지만 Git bash 를 이용할 경우에 설정 파일을 직접 편집하도록 할 수도 있다.
1 |
git config -e --global |
1 2 3 |
git branch # 로컬 브랜치만 보기 git branch -a # 로컬, 원격 모두 보기 git branch -r # 원격 브랜치만 보기 |
1 |
git branch -d <브랜치 이름> |
원격 브랜치 삭제는 branch 명령어를 사용하지 않는다.
1 |
git push origin --delete <원격 브랜치 이름> |
원격 브랜치 목록 보기를 했을때에 실제 원격 브랜치와 차이가 있을 수 있다. 이것때문에 헷깔릴 수 있는데, 원격 브랜치 목록을 로컬에 반영하기 위해서는 다음과 같이 해준다.
1 2 3 |
git remote update origin --prune git remote prune origin git fetch --prune |
prune 을 자동으로 되도록 설정할 수 있다.
1 2 |
git config --global remote.origin.prune true # origin 저장소에 prune 설정 git config --global fetch.prune true # 모든 fetch 작업에서 prune 활성화 |
git 설정 파일에서는 다음과 같이 설정할 수 있다.
1 2 3 4 5 6 7 8 9 |
# git config --global fetch.prune true [fetch] prune = true # git config remote.origin.prune true [remote "origin"] url = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx fetch = +refs/heads/*:refs/remotes/origin/* prune = true |
node_exporter 는 OS 에 대한 각종 지표를 수집해주는 exporter 다. Prometheus 가 읽어 갈수 있도록 작은 웹서버로 작동된다.
설치야 바이너리로 배포를 하기 때문에 아키텍쳐에 맞게 다운받아서 설치를 하면 된다. 압축 풀고 시작하면 그만일 정도로 아주 간단하다. Prometheus 에 exporter들은 대부분 간단하다. 복잡하게 설치하지는 않는다.
그런데… 고려해야하는 부분이 존재한다. 일단, 설치부터…
다운로드는 Github 저장소에 받으면 된다.
1 2 |
curl -LJ https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz | tar -xvz mv -v node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin |
node_exporter 디렉토리가 보이고 그 안에 node_exporter 바이너파일이 있다. 이것을 적당한 곳으로 이동시키놓으면 끝난다.
여기서 이제 고민을 해야한다. 많은 사람들은 이것을 쉘 스크립트와 nohup 을 사용하는 사람들이 있다. 어느 시대에 살고 있는 사람들인지 의심이 될 정도인데, 이제는 init script 도 다 없어질 만큼 대부분의 배포판들이 systemd 로 다 전환이 완료된 상태다.
그러면 당연히 systemd 로 하면 되지! 하지만 여기서 문제가 된다.
현재 systemd 는 지속적으로 지금도 버전업이 되고 있다. 그러다보니 특정 버전을 기준으로 특정 기능이 지원이되고 안되고가 갈리게 된다.
systemd 버전 240 …. (대체 어떻게 버전 관리를.. 어떻게 기능을 많이 집어넣었으면 버전이 240 이여.. -_-;; ) 왠만하면 systemd 버전 240 이상을 사용할 것을 권한다. 그런데, 이게 말처럼,, 240버전을 써라~~ 한다고 되는게 아니다.
systemd 는 리눅스 시스템의 뼈대라고 보면된다. 핵심중에 핵심! 그러다보니 systemd 는 배포판과 함께 제공되고 묶여 있다. 240버전을 쓰고 싶다면 240버전을 가진 배포판을 써야 한다는 뜻이 된다.
이런 저런 사유로 배포판을 선택하고 거기다 버전을 선택하게 된다. 내가 하고 있는 프로젝트에서는 CentOS, RHEL 7.9 가 대부분이고 RHEL 8 은 최신형으로 취급하는데.. systemd 만 놓고 보면 RHEL 8 도 그다지 마음에 들지 않는 부분이다.
개인적으로 RHEL 8 도 이제는 끝물이다. RHEL 9 의 버전이 이제는 벌써 9.3을 벗어나고 있기 때문에 이제는 RHEL 9 로가야 한다.
아무튼, 말이 길었는데, systemd 유닛으로 만들어 보자..
일단, node_exporter 에는 많은 옵션들이 있다. Prometheus exporter 들이 많은 옵션들을 제공한다. 이러한 옵션들은 별도의 파일로 작성하고 쉘 변수로 만들어 두고 systemd 유닛에서 읽어들이도록 하면 된다.
/etc/sysconfig/node_exporter 파일에 다음과 같이 내용을 적어준다.
1 |
OPTIONS='--web.listen-address=":9100" --collector.disable-defaults --collector.cpu --collector.loadavg --collector.xfs --collector.meminfo --collector.filesystem --collector.diskstats --collector.uname --collector.vmstat --collector.filesystem.fs-types-exclude="^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|tmpfs|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$" --collector.netdev --collector.stat --collector.tcpstat --collector.processes --collector.diskstats.device-exclude="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$"' |
/etc/sysconfig/node_exporter 는 RedHat 기반에 적합하다. Ubuntu 면 /etc/sysconfig 디렉토리가 없기 때문에 Ubuntu 레이아웃에 맞는 곳에 넣으면 된다.
systemd 유닛 파일은 별거 없다.
1 2 3 4 5 6 7 8 9 10 11 |
[Unit] Description=Node Exporter Wants=network-online.target After=network-online.target [Service] EnvironmentFile=/etc/sysconfig/node_exporter ExecStart=/usr/local/bin/node_exporter $OPTIONS [Install] WantedBy=multi-user.target |
딱 보면 별거 없다….. 하지만,,, 240 이하에서는 출력되는 로그들… 일명 Standard Out 들을 어떻게 처리할까? 그냥 이대로 둬도 되나? 결론은 되긴 한다. 이렇게 그대로 두면 node_exporter 가 뭔가를 출력하면 stdout, stderr 로 내보낸다. 그러면 systemd 는 이것을 /var/log/syslog 파일에 기록하게 된다.
하지만, systemd 로 변경되면서 나온 journal 에 기록을 하고 싶을지도 모른다. 이왕이면 그렇게하는게 좋기도 하다. 그래서 다음과 같이 [Service] 세션에 StandardOutput 옵션을 준다.
1 |
StandardOutput=journal+console |
콘솔에도 출력을…. 뭐.. 이건 옵션이다. 여기서 systemd 버전에 따라서 파일에 redirect 가 가능하기도 하고 불가능하기도 하다. StandardOutput 에 옵션이 inherit, null, tty, journal, kmsg, journal+console, kmsg+console, file:path, append:path, truncate:path 이렇게 되어 있다. 이게 다 가능한게 아니다. 버전에 따라서 가능하기도 하고 불가능하기도 하다.
새로운 배포판에 따라서 systemd 의 버전이 달라진다. 문제는 대부분 systemd 버전이 특정 시점까지만 업데이트가 된다. 시스템에 뼈대이다 보니 확 갈아 엎을 수 없는 것이여서 그럴거다.
이러다보니 특정 기능을 탐이 나는 때가 있는데, OS 를 다 갈아 엎어야하는 고충이 있다. 그래서 이왕이면 새로운 시스템을 구축할때에는 왠만하면 최신판을 쓰는게 좋다. Ubuntu 라면 24.04, RedHat 이면 9.0 을 사용하길 권한다.
이글은 다음의 글을 번역한 것입니다.
나는 대략 다음과 같은 구조로 Nginx 와 또 다른 프론트 로드 밸런서 뒤에 webapp 을 가지고 있다.
Client(a.a.a.a) -> LB(b.b.b.b) -> NGX(c.c.c.c) -> WEBAPP(d.d.d.d)
이것이 내 Nginx 설정의 일부다.
1 2 3 4 5 6 7 8 |
location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; real_ip_header X-Forwarded-For; set_real_ip_from b.b.b.b; real_ip_recursive on; } |
1. 로드 밸런서는 X-Forwarded-For 필드에 Client IP 를 추가 한다.
1 |
X-Forwarded-For = a.a.a.a |
2. Nginx 는 X-Forwarded-For 헤더에서 LB IP(b.b.b.b) 를 생략하고 Client 에 Real IP를 찾는데, $remote_addr 은 b.b.b.b 에서 a.a.a.a 로 변경되고 따라서 proxy_set_header X-Real-IP $remote_addr 은 맞는 설정이다. (내가 원하는 설정대로다.)
그런데, Nginx 는 X-Forwarded-For 헤더를 b.b.b.b 대신에 a.a.a.a IP 로 바꾼다.
3. WEBAPP 은 다음과 같은 헤더를 수신한다.
1 2 3 |
X-Forwarded-For = a.a.a.a, a.a.a.a X-Real-IP = a.a.a.a -> X-Forwarded-For 는 a.a.a.a, b.b.b.b 여야 한다. |
내가 필요한 것은 먼저 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_forwarded_for를 설정한 다음 실제 IP를 검색하고 $remote_addr 값을 바꾸는 기능입니다.
이 문제를 어떻게 해결해야 하는지 알려줄 사람?
답1
$proxy_add_x_forwarded_for
는 $http_x_forwarded_for,$remote_addr 와 동일하고 $remote_addr
값은 http_realip_module
을 사용될때에 변경됩니다. 그래서 당신은 그 헤더에서 마지막 Proxy 주소를 얻을 수 없습니다. nginx 설정은 선언적이기 때문에 지시어의 순서 변경은 영향을 주지 않습니다.
http_realip_module
를 사용하면, $realip_remote_addr
값은 (nginx >= 1.9.7
) 오리지널 $remote_addr 처럼 사용될 수 있습니다. (역, $realip_remote_addr 은 Nginx 앞에 있는 서버에 IP, 여기서는 LB(b.b.b.b) 를 가리킨다) 따라서 다음과 같이 X-Forwarded-For 를 세팅할 수 있습니다.
1 |
proxy_set_header X-Forwarded-For "$http_x_forwarded_for, $realip_remote_addr"; |
답2
나도 같은 문제로 여기까지 왔는데, 이러한 현상은 real_ip_recursive on; 으로 발생된다는 결론을 내렸습니다. Nginx 의 공식문서에 다음과 같이 나옵니다.
If recursive search is enabled, an original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field.
당신은 b.b.b.b 를 신뢰하도록 만들었다. 그래서 기대했던 a.a.a.a, b.b.b.b 가 a.a.a.a, a.a.a.a 로 바뀐 것입니다. 다음의 소스가 나에게 확신을 주었다. https://serverfault.com/questions/314574/nginx-real-ip-header-and-x-forwarded-for-seems-wrong
Spring Boot3 에서 Reactive Web 이 아닌 그냥 Web 을 한다고 하면 Servlet 기반이고, Spring Boot 앱을 실행했을 경우 기본적으로 Embedded Tomcat 이 구동된다.
만일 다음과 같은 환경이라고 가정해 보자.
Client —-> AWS ALB ——> Nginx —–> Spring Boot3 (Embedded Tomca)
‘어느 미친놈이 저런 구조로 아키를 설계하고 구현하냐?’ 라고 비아냥될 수도 있지만 실제로 이렇게 하는 곳이 있다. 이런 구조에서 Spring Boot3 개발자은 다음과 같은 요구사항을 인프라에 전달 한다.
Real Ip 를 가지고 올 수 있게 해주세요.
Spring Boot3 에서 Real Ip, 그러니까 Client 의 IP 를 가지고 오는 방법으로 다음과 같은 코드를 자주 사용한다.
1 2 |
HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); ip = req.getRemoteAddr(); |
이렇게 해서 돌려보면 ip 에는 Nginx 의 ip를 가지고 오게 된다. 이를 해결하기 위한 다양한 방법이 존재한다.
Nginx 에서 Real IP 를 가지고 오기 위해서는 Nginx 에 자체 변수인 $remote_addr 에 Client IP 를 넣어줘야 한다. 여기서 ‘$remote_addr 변수에 값을 넣어줘야’ 말이 중요하다.
Nginx 에서도 앞에 수많은 Proxy 가 있을 경우에 $remote_addr 은 이전 Proxy 의 IP 주소가 된다.
Client —-> AWS ALB ——> Nginx
만일 위와같은 구조일 경우에 Nginx 에 $remote_addr 값은 AWS ALB 의 값이 된다.
이 문제를 해결하기 위해서 Nginx 에 ‘–with-http_realip_module’ 을 가지고 있을 경우에 특정 헤더에서 Real Ip 를 찾을 수 있도록 해준다. AWS ALB 의 경우에는 X-Forwarded-For 헤더에 Client IP 를 보존해 준다. 따라서 Nginx 에서는 다음과 같이 설정해줌으로써 $remote_addr 에 Client IP를 넣을 수 있다.
1 2 3 4 |
set_real_ip_from 172.10.10.0/24; # ALB A zone set_real_ip_from 172.10.20.0/24; # ALB C zone real_ip_header X-Forwarded-For; real_ip_recursive on; |
X-Forwarded-For 라는 헤더에서 Client IP 를 찾아야 하는데, set_real_ip_from 에 있는 IP 는 그냥 신뢰할 수 있는 IP 로 정의하고 Client IP 에서 제외된다. 이렇게 하는 이유는 X-Forwarded-For 가 다음과 같은 구조를 가지기 때문이다.
X-Forwarded-For: 213.13.24.10, 172.10.10.34
신뢰할 수 있는 IP 라는 건 Proxied IP 를 말하는 것으로 중간에 있는 서버들을 말한다. 이러한 신뢰할 수 있는 IP 가 X-Forwarded-For 에 있기 때문에 이것은 Client IP가 될 수 없다. 이 신뢰할 수 있는 IP 를 제외하고 나면 Client IP 만 남게 되고 이것을 $remote_addr 변수에 담게 된다.
이렇게하면 끝났으면 좋을련만, Nginx 뒤에 있는 Spring Boot3 에 req.getRemoteAdd() 함수에는 여전히 Client IP가 잡히지 않는다. Nginx 에 $remote_addr 은 어디까지나 Nginx 내에서만 활용되는 것이고 뒷단에 연결된 서버까지 연향을 주지 않는다.
이 경우에는 별도의 Header 를 정의해서 그 Header 값을 가지고 옴으로써 Client IP를 얻을 수 있다. 먼저 Nginx 에서 Header 값을 지정해줘야 한다. 다음과 같이 proxy_set_header 를 이용해 X-Real-IP 에 $remote_addr 값을 담아 준다.
1 |
proxy_set_header X-Real-IP $remote_addr; |
이렇게 하면 다음과 같은 코드로 Client IP 를 가지고 올 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
private String[] headerTypes = {"X-Real-IP", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"}; private String ip; @GetMapping(value = "/getIp") public String getIp() { HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); for(String headerType: headerTypes) { ip = req.getHeader(headerType); if(ip != null) break; } if (ip == null) ip = req.getRemoteAddr(); log.info("Real Remote(Client) IP Address: " + ip); return ip; } |
Nginx 에서 설정을 하게 되면 결국 Spring Boot3 에서 Nginx 에서 넘겨주는 Client IP 를 담고 있는 별도의 Header 값을 가지고 와야 하는 코드를 작성해야 한다.
원래 Tomcat 에서는 Valve 를 이용해서 Real IP 를 가지고 올 수 있다. 놀랍게도 이 방법은 Nginx 의 설정과 방법과 동일하고 문법만 다르다. 신뢰할 수 있는 IP 대역을 지정하고 체크할 Header 를 지정해 주면 된다. 이것을 Spring Boot3 에서는 application.properties 에 설정만으로 간단하게 할 수 있다.
다음과 같다.
1 2 3 4 5 6 7 8 9 |
server.forward-headers-strategy: native server.tomcat.remoteip.remote-ip-header=x-forwarded-for server.tomcat.remoteip.internal-proxies=10\.\d{1,3}\.\d{1,3}\.\d{1,3}|\ 169\.254\.\d{1,3}\.\d{1,3}|\ 127\.\d{1,3}\.\d{1,3}\.\d{1,3}|\ 172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|\ 172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|\ 172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}|\ 192\.168\.96\.78 |
internal-proxies 는 신뢰할 IP 설정이라고 보면 되고, Nginx 에서 set_real_ip_from 설정이며, remote-ip-header 는 어느 헤더에서 찾을지를 지정하는 것으로 Nginx 에서 real_ip_header 와 같다.
이렇게 하면 Tomcat 은 Servlet 객체에 Client Ip 를 담아주게 되고 req.getRemoteAddr() 호출만으로, 추가적인 코딩 없이 Client Ip 를 가지고 올 수 있게 된다.
최근들어 arm64 아키텍쳐가 인기가 많아졌다. 애플의 실리콘 반도체라고 불리는것도 arm64 기반이며 Windows 11 도 arm64 에서도 작동된다. 리눅스는 오래전부터 다양한 아키텍쳐로 포팅이되었기 때문에 arm64 를 위한 배포판도 다양하게 존재한다. 문제는 arm64 아키텍쳐를 경험하기 위해서 arm64 하드웨어가 있어야 했지만, 이제는 x86_64 기반의 가상머신을 이용하면 arm64 아키텍쳐를 게스트로 운영할 수 있다.
이 문서는 x86_64 기반 가상머신에서 arm64 아키텍쳐기반의 게스트를 실행하는 방법에 대해서 기술한 것이다.
x86_64 아키텍쳐 기반의 가상머신으로 리눅스 운영체제를 기반으로 KVM 을 활용하고 있다. GUI 툴로서 virt-manager, CLI 로는 virsh 를 활용해서 간단하게 게스트를 생성하고 운영하고 있다. arm64 아키텍쳐 게스트를 운영하기 위한 호스트로서 x86_64 아키텍쳐 기반 가상머신 스펙은 다음과 같다.
arm64 아키텍쳐기반 게스트를 운영하기 위해서는 QEMU 를 사용해야 한다. QEMU 는 가상머신 에뮬레이터라고 생각하면 된다. 문제는 QEMU 는 CLI 기반만 제공한다.
반면에 libvirt 는 KVM/QEMU 등을 지원하는 일종의 핸들러 라이브러리고 생각하면 된다. libvirt 를 이용하면 xml 기반으로 게스트 관련 가상머신 스펙을 정의할 수 있으며 virt-manager 와같은 GUI 툴도 활용할 수 있다.
QEMU 에뮬레이터라고 했기 때문에 arm64 를 위한 QEMU 에뮬레이터를 설치하면 arm64 기반 게스트 운영체제를 운영할 수 있다. 다음과 같이 arm64 를 위한 QEMU 에뮬레이터를 설치해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ sudo apt install qemu-system-arm Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: guestfish guestmount libconfig9 libguestfs-perl libstring-shellquote-perl libsys-virt-perl libwin-hivex-perl libxml-parser-perl libxml-xpath-perl Use 'apt autoremove' to remove them. The following additional packages will be installed: qemu-efi-aarch64 qemu-efi-arm Suggested packages: vde2 The following NEW packages will be installed: qemu-efi-aarch64 qemu-efi-arm qemu-system-arm 0 upgraded, 3 newly installed, 0 to remove and 2 not upgraded. Need to get 15.8 MB of archives. After this operation, 532 MB of additional disk space will be used. |
위 패키지를 설치가 완료되면 다음과 같이 virt-manager 에서 게스트를 생성할때에 Architecture options 이 생긴다.
Ubuntu22.04 에서는 이 과정이 필요하지 않다.
arm64 게스트 실행을 위해서 파일이 필요하다. 첫번째로 NVRAM 변수들을 저장하기 위한 플래쉬 볼륨(Flash volume) 을 생성해야 한다.
1 |
]$ truncate -s 64m varstore.img |
두번째로 ARM UEFI 펌웨어 파일이 필요하다.
1 2 |
]$ truncate -s 64m efi.img ]$ dd if=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd of=efi.img conv=notrunc |
이제 필요한 사항은 모두 갖춰졌다.
처음부터 Arm64 기반 OS 를 게스트로 설치하면서 생성할 수도 있다. 하지만 이미 있는 Arm64 기반 OS를 가져다 쓸 수도 있다. 여기서는 Amazon Linux 를 가져다 사용해 보도록 하겠다.
Amazon Linux 는 Amazon 이 AWS 서비스에서 사용할 목적으로 만든 배포판이다. 현재 Amazon Linux2 와 Amazon Linux3 등 다양한 버전을 제공한다. 최근 프로젝트가 Amazon Linux2 를 많이 사용하고 있어서 Amazon Linux2 Arm64 기반 OS 이미지를 게스트로 한번 실행 보도록 하겠다.
Amazon Linux2 는 다음과같이 다운로드 할 수 있다. 이미지 파일은 Amazon Linux 2 virtual machine images 에서 찾을 수 있다.
1 |
]$ curl -LJO https://cdn.amazonlinux.com/os-images/2.0.20240610.1/kvm-arm64/amzn2-kvm-2.0.20240610.1-arm64.xfs.gpt.qcow2 |
Amazon Linux2 는 기본적으로 ec2-user 라는 시스템 계정이 있으며, 로그인을 위해 패스워드 방식이 아닌 SSH 인증키 방식을 사용한다. 하지만 배포되는 이미지에 맞는 인증키가 따로 없기 때문에 부팅과정에서 이 부분을 변경하도록 해야하는데, 이를 위해서 seed.iso 를 만들어 게스트 OS 에 CD-ROM 에 넣어 부팅해준다. 이 부분에 대한 설명은 다음의 페이지에서 찾을 수 있다.
간단하게, 시스템 호스트 이름(나중에 변경하면 된다) 과 ec2-user 에 로그인 패스워드를 변경하도록 seed.iso 파일을 만들어 보도록 하겠다.
먼저 작업을 위한 디렉토리 seedconfig 만들고 meta-data, user-data 파일을 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
]$ mkdir seedconfig ]$ vim meta-data local-hostname: amazonlinux.onprem ]$ vim user-data #cloud-config #vim:syntax=yaml users: # A user by the name `ec2-user` is created in the image by default. - default chpasswd: list: | ec2-user:amazon # In the above line, do not add any spaces after 'ec2-user:'. |
로그인이 가능하도록 필요한 부분만 넣었다. 이제 다음과 같이 seed.iso 파일을 생성해 준다.
1 2 3 4 5 6 7 8 |
]$ genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data I: -input-charset not specified, using utf-8 (detected in locale settings) Total translation table size: 0 Total rockridge attributes bytes: 331 Total directory bytes: 0 Path table size(bytes): 10 Max brk space used 0 183 extents written (0 MB) |
virt-manager 로 Amazon Linux2 생성하기
이제 준비할 것들은 모두 갖췄다. virt-manager 를 이용해서 Amazon Linux2 를 구동해 보자.
OS 이미지가 있기 때문에 Import 로 하고 Arm64 는 aarch64 로 선택, Machine Type 은 virt 다.
다운로드 받은 amazon linux2 이미지와 운영체제 종류를 선택한다. 운영체제 종류를 잘 모르겠다면 Generic Linux 로 해도 된다.
Memory, Cpu 는 사양에 맞게 조절해주고 다음을 선택한다.
가상머신 이름을 지정하고 네트워크 선택을 한다음에 반드시 Customize configuration before install 를 체크해 준다. 그리고 Finish 를 하면 다음과 같은 화면이 나온다.
Firmware 를 Custom 으로 하고 no-secboot.fd 선택해 준다. 그리고 설치를 시작해 준다.
정상적으로 부팅이 된다. 로그인이 안되기 때문에 앞에서 만든 seed.iso 파일을 이용해야 한다. 이를 위해서 Amazon Linux2 게스트 OS 에 CD-ROM 하드웨어를 추가해 준다.
이제 VM 을 다시 시작시키면 seed.iso 에 user-data 에 설정한 ec2-user 의 패스워드로 로그인이 가능해 진다.
정상적으로 로그인이 성공했다. ec2-user 는 기본적으로 sudoer 권한을 가지고 있기 때문에 sudo 를 이용해서 root 작업을 할 수 있다.
sshd 에 설정에서 패스워드 인증을 활성화 해준다.
1 2 |
- 65 PasswordAuthentication no + 65 PasswordAuthentication yes |
설정을 변경해 줬기 때문에 sshd 를 재시작 해준다.
이렇게 sshd 로 패스워드 인증방식을 활성화 했기 때문에 원격에서 접속도 가능해진다.
마지막으로 Amazon Linux2 게스트 를 셧다운 해주고 seed.iso 를 위한 CD-ROM 하드웨어를 삭제해준다.
systemctl 은 리눅스에 서비스 데몬을 설정하는 것과 유사하다. 과거 init script 를 systemd 로 전환하면서 만들어진 것인데, 문제는 시스템의 서비스 데몬 등록이라서 대부분 root 권한으로 실행된다. 만일 일반 사용자가 systemd 유닛으로 등록하기 위해서는 어떻게 해야 할까…
사용자 홈디렉토리에 ~/.config/systemd/user 디렉토리를 생성한다. 이 디렉토리에 사용자 systemd 유닛 파일을 작성해야 한다.
systemd 유닛 파일의 확장자는 service 다. 그리고 반드시 다음과 같이 WantedBy 값을 default.target 으로 해줘야 한다. 가끔 multi-user.target 으로 하는 경우가 있는데, 이걸로 할 경우 부팅시에 자동으로 실행되지 않는다.
1 2 |
[Install] WantedBy=default.target |
이제 다음과 같이 사용자 서비스를 활성화 해준다. 이렇게 함으로써 부팅시에 자동으로 서비스가 시작된다.
1 |
]$ systemctl --user enable test.service |
이렇게 세팅을 하게되면 리눅스 서버가 부팅될때마다 사용자 서비스도 함께 자동으로 실행이 된다.
systemctl –user 는 일반사용자가 사용하는 명령어다. 하지만, root 사용자가 systemctl –user 명령어를 사용할 수 있을까? systemd 248 (released March 2021) 버전에서 -M username@ 옵션을 통해서 root 사용자가 명령어를 실행할 수 있다.
1 |
]# systemctl --user -M user1@ status myunit.service |