이 상황에서 su user1으로 들어가서 image를 다시
build하면 error 가 난다. Error: error creating tmpdir: mkdir /run/user/1000: permission denied
podman이 temporary files
directory
이 디렉토리는 2가지 용도로 사용
directory 를 sentinel file 을 저장해서 restart 를 감지하는데
쓰고,
container가 재시작할 때 다시 생성되는 container content 를 저장,
예를 들면, /etc/resolv.conf
그래서 podman 이 시작된 후에 이 directory 를 바꾸는 것은 심각한
문제를 일으킬 수 있다.
podman 이 restart 를
감지해야 하는 이유
재부팅되면, podman 은 refreshing the state 를 해야한다.
재부팅이 되면
모든 container들은 더 이상 running 하지 않는다.
모든 container filesystem들은 unmount된다.
모든 network interface들은 새롭게 만들어질 필요가 있다.
podman은 이것들을 반영하기 위해서 podman database를 update할 필요가
있다.
그리고 container를 launch 할 준비가 됐다고 확신시켜주기 위한
per-boot setup 을 할 필요가 있다.
이것을 ’refreshing the state’라고 한다.
‘refreshing the state’
다음의 동작을 ‘refreshing the state’ 라고 부른다.
podman은 reboot 될 때의 상태를 podman database에 update할 필요가
있다.
그리고 container를 launch 할 준비가 됐다고 확신시켜주기 위해
per-boot setup 을 할 필요가 있다.
필요한 이유:
이것은 podman 은 deamon 이 아니기 때문에 필요하다.(즉, podman이 항상
떠 있지 않아서?)
각각의 podman command 는 새로운 process로 실행된다. 처음에
container들이 어떤 상태인지 모르는 상태로 실행된다.
그래서 database를 보고, 모든 container의 정확한 현재 모습과 상태들을
알 수 있다.
이 그림이 계속 정확하게 유지되기 위해서, reboot후에 ‘refreshing the
state’ 는 필수다.
history
refresh 를 수행하려면, system이 reboot 됐는지를 알 수 있는 방법이
필요하다.
개발초기, Podman team 은 tmpfs filesystem 에서 보초병
파일(sentinel file)을 만들어 사용하기로 정했다.
이것은 in-memory filesystem 이다. 그래서 reboot 하면 이전 정보가
사라진다.
Podman 은 이 tmpfs 에 file 이 존재하는지 여부를 보고, 없으면 file을
만드는 것을 통해, 이 system reboot 이후 처음인지 여부를 알 수 있다.
문제는 어디에 temporary files directory 를 넣어야 하는가를 결정하는
것이다.
명확한 답은 /tmp 이다. 하지만 /tmp가 항상
tmpfs filesystem 이 라는 법은 없다.
대신에, 기본적으로, Podman 은 /run을 이용한다. 이곳은
tmpfs 라는 것이 보장된다.
다만 /run은 root 에 의해서만 write 이 가능하다.
그래서 rootless podman 은 다른 곳을 찾았다. 그곳이
/run/user/$uid 이다. (/run/user/$uid 에 대한
이야기는 ref.2
를 참고)
이 directory 가 만들어지려면, PAM 설정이 필요하다.(ref. 2 에 따르면
이 폴더는 pam_systemd에서 만든다.)
Rootless Podman 은 만약 시스템들이 이 directory 를 지원하지 않으면,
/tmp를 사용하게 된다.
물론 이것도 /tmp 가 tmpfs 가 아닐 가능성은 있지만, 더
나은 방법이 없다.
long-running container
사용할때
이 디렉토리는 user session 이 만들어질때 만들어지고, user session 이
사라질때 자동으로 지워진다.
이 때 문제는 user session 으로 들어와서 podman 을 실행하고, logout
을 해버리면, run/user/$uid가 사라지고, 이것은 Podman 이
refresh the state 를 하고, 현재 running 하고 있는 container들이 running
하지 않다고 표시하게 된다.
그래서 logind-managed system에서는 persistent user session 을 만들
수 있는 option 이 있다.(login enable-linger)
이 login enable-linger 은 long-running container들을
실행하는 user들은 모두 이 것을 이용해야 한다.
su, sudo
su, sudo는 login session 을 만들지 않는다.
그래서 /run/user/$uid 를 만들지 않는다.
그렇기 때문에, Rootless podman 을 사용할 때 su,
sudo로 사용하면 안된다. Root container들은 문제가
없다.
다만, loginctl enable-linger 를 사용해서 그 user에
대해서 영구적인 user session 을 만들면 가능하다.
sudo, su 대신에 user session 을
만들어주는, machinectl login 또는 ssh 를
사용해서 접근하면 된다.
su
와 sudo 를 사용해서 rootless podman 을 실행하는 법
처음 시작시에 sudo 또는 su로 Podman 을
실행하면, /tmp가 temporary files directory로 잡혀서
실행가능
--runroot flag 를 이용해서 temporary files directory
path 를 지정해서 사용할 수 있다.
다만 이것들은 cgroups v1 system에서만 가능. 그리고 정확한 환경변수를
위해 --login argument가 필요할 것이다.
cgroups v2 system 에서 하려면, cgroup 들을 setup 하고, rootless
container에 대한 resource limit 들을 setup 하기 위해 login session 의
다른 부분들이 더 필요
podman 에서는 해당 계정에서 만든 container들은 해당 계정으로만 볼 수
있다. 그래서 당연히 실행도 해당계정으로만 해야 한다. 그래서 만약 user1
로 만든 container는 다른 계정에서 sudo 등을 이용해서 실행할
수 없다.
그리고, root 도 non-root user가 실행한 container를 볼 수 없다.(ref.
1)
ref. 3 을 보면, 자세한 설명이 나온다. 여기서 간략하게 추려보면
podman 은 실행시점에 temp directory 가 필요한데 이 temp directory 로
/run/user/$UID 를 이용한다. 만약 이 directory 를 사용할 수
없다면, /tmp를 이용하게 된다. 그런데 이 결정은 podman 이
처음 run 할때 정해지고는 변경되지 않는다.
이 directory 는 login 할
때 만들어진다. 그리고 logout 하면 지워진다.
그런데 su나 sudo를 이용하면 login session
이 만들어지지 않는다. 그래서 /run/user/$UID 가 없다.
root container 들은 괜찮다. 그들은 /run/user/$UID
대신에 /run을 사용하기 때문에.
그래서 su나 sudo를 이용해서 rootless
container를 실행하는 것은 권장하지 않는다.
그래서 첫 실행에 /tmp를 실행하도록 만들기도 한다.
그러나 이것도 문제는 있다. 이부분은 ref. 3 을 확인하자.
CNCF(Cloud Native Computing Foundation) ecosystem 의 일부다
transport protocol 로 HTTP/2 를 이용
Protocol Buffers 를 이용한다.
json 에 비해 message size는 60-80% 작고, 약 8배정보 빠르다.
HTTP/2 의 이점
binary framing protocol: 텍스트 기반인 HTTP 1.1과 달리 데이터 전송이 가능하다.
multiplexing 지원 : 여러병렬 요청들을 하나의 연결로 보낼 수 있다. - HTTP 1.1은 한 번에 하나의 요청/응답 메시지 처리만 가능
Bidriectional full-duplex 통신 : 클라이언트 요청과 서버 응답을 동시에 보낼 수 있다..
Built-in streaming : request 들과 response들이 비동기적으로 large data set 들을 stream 하는 것을 가능하게 해준다.
Header 압축 : 네트워크 사용량을 줄여준다.
Protocol Buffers
cross-platform IDL(Interface Definition Language)을 이용해서, 개발자들은 각 microservice를 위한 service contract 를 정의하게 된다.
이 contract 는 text 기반의 .proto file 로 구현된다.
이 contract 가 각 서비스에 대한 method, input, output을 정의하게 된다.
platform 이 다른 server와 client 가 있다고 해도 양쪽에서 같은 contract file 을 사용한다.
이 .proto file을 protoc를 이용해서 compile 한다. 그러면 target platform 에 대한 client code 와 service code를 만들어 준다. code는 다음 내용을 가지고 있다.
Strongly typed objects :
이 object들은 client 와 service 사이에서 공유된다.
service 작업들과 message를 위한 data 요소들 표현한다.
A strongly typed base class 는 remote gPRC service 가 상속하고, 확장할 수 있는 필수 netowrk 연결(network plubming) 을 가지고 있다.
A client stub : 이 stub 는 remote gRPC service 를 호출하기 위한 필수 plubing 을 포함한다.
envoy proxy server
browser client 를 위한 gRPC의 javascript 구현이 gRPC-Web 이다. gRPC-web client 들은 gRPC service들에 접근할 때 Envoy(proxy)를 이용해서 연결하게 된다
envoy 가 필요한 이유:
브라우저에서 HTTP/1.1 request 를 보내면 그것을 받아서 gRPC request 들로 변환해서 이것을 gRPC service server 로 넘겨주고, 다시 이 서버에서 오는 응답을 client 에게 다시 HTTP/1.1 로 변환해서 넘겨주는 역할을 하게 된다.
envoy proxy server가 web browser에서 보내는 gRPC 요청을 받아서 gRPC server로 넘겨준다.
이것은 기본적으로 불가능하다. 단순하게 생각하면, server 가 request 를 보낸다고 하면, 그것을 받아줄 server가 존재해야 한다. 그럼 어떻게 할까?
예전에는 이것을 위해서 계속 client 에서 물어보는 방법을 택했다.
1. polling
계속 client 에서 server에게 물어보는 것이다. 너 나한테 뭐 보낼것 없니? 라고. 그러다 서버가 그래 이것좀 처리해줘 하고 주면, 그것을 받아서 처리한다.
이것의 문제는 쓸데없이 자꾸 server에게 request 를 보내야 한다는 것이다. 그냥 단순히 물어보기만 하는 request 라도 서버는 그것이 단순히 물어보는 request인지를 판별하기 위한 resource를 소모한다. 그러므로 많은 client 가 동시에 그런일을 한다고 가정한다면 이것은 꽤나 부하가 될 수 있다.
ref. 1 에 long polling 이 있는데, 그것은 short polling 보다 비효율적이다. long polling 은 request 를 받은 서버가 client 와 connection 을 오랜시간동안 유지한다는 이야기인데, 이렇게 되면 특정시간내에 더 적은client를 처리할 수 밖에 없다.
그런데 이제 browser에서 SSE 라는 것을 지원하기 시작했다.(2009년 4월)
2. SSE(Server Sent Event)
client 에서 한번 서버와 연결한 이후 주기적으로 서버는 이벤트를 보낼 수 있게 된다.
양방향(full duplex)는 아니다. 서버에서만 보내게 된다.
예를 들어, 주식의 실시간차트 같은 것들을 이 SSE로 구현할 수 있다.
3. WebSocket
WebSocket protocol 은 2011년에 표준화 됐다.[ref. 3]
서버측에서 client 로 event를 보내는 방법을 제공해 준다.
기본적으로 http 가 사용하는 TCP 는 양방향 통신이 가능했지만, HTTP 는 그렇지 않다.
그래서 이 WebSocket은 TCP 위에 새로운 protocol 을 만들어서, polling을 하지 않고, client server간의 event를 수시로 아무때나 주고받을 수 있도록 connection 을 열어놓도록 설계했다.
WebSocket
connection 을 맺을 때는 http header에 특정 field를 넣어줘야 한다. 그러면 browser에서 이 header를 보고 WebSocket protocol 로 전환한다. 그리고 나서 browser가 서버쪽에 Sec-WebSocket-Key에 random하게 만든 key를 base64-encoding 해서 보내게 된다. 그러면 서버는 응답에 Sec-WebSocket-Accept 를 보내준다. 그리고 이후로 data를 WebSocket protocol 을 이용해서 주고받게 된다.(아래 그림 참고)
OpenAI가 사람의 글쓰기와 AI 생성 텍스트를 구별하는 것을 목표로 한 도구의 정확도가 낮아서 종료하기로 결정 업데이트된 블로그 글 내용에서, OpenAI는 7월 20일을 기준으로 이 AI 판별기(classifier)를 중단하기로 했다고 밝혔습니다. “우리는 피드백을 반영해 현재 더 효과적인 텍스트 출처 기술에 대해 연구 중입니다.”라고 회사 측은 말했습니다.
[인공지능 탐지기가 미국 헌법이 인공지능에 의해 작성되었다고 생각하는 이유 - All Things IT @AI](https://ai.atsit.in/posts/9244386115/), 2023-07-14 : ai 감지 개념에 대한 이야기