4 minute read


project

epis

고민되는 점이.. k8s를 쓰면 그게 대부분 인프라를 관리하므로 마이크로서비스 아키텍쳐의 각 패턴들을 공부하는데는 조금 애매하지 않을까 싶다. consul와 k8s를 같이 찾아볼 때에도 보통 k8s 클러스터와 외부 통신을 연동시킬때 쓴다고 하는 것 같다.

클러스터 구성 자체는 간단한거 같다. 마스터 노드 즉 명령을 내릴 수 있는 노드는 한개로 제한되는건가? https://rancher.com/docs/k3s/latest/en/quick-start/ 위 설명대로, 다른 pc에서 토큰과 url 지정해서 구성하니 해당 pc에서는 sudo k3s kubectl get no 명령이 실행되지 않는다. worker node이기 때문에 그런 듯하다.

k8s 공부

구조

  • control plane
    • api server
      • scheduler
      • controller-manager
      • cloud-controller-manager
  • nodes
    • proxy
    • kubelet
      • container runtime

api 서버가 scheduler, controller, nodes와 통신

강의에서는 kubeadm으로 셋업한다는데, 나는 k3s로 일단 구성은 되었다고 생각한다.

클러스터 셋업

우분투에서 대략적인 셋업 방법인데, 나는 k3s로 구성했으므로 일단 스킵, 좀 불안하긴하다. 모든 과정 상세히 적어봐야 큰 의미 없을듯하여 대략적으로 절차만 기술함.

네트워크 설정

클라우드에서는 보통 호스트 이름이 랜덤 해쉬값으로 지정되는데, 우분투에서는 다음 명령으로 호스트 이름을 지정할 수 있는 듯하다: sudo hostnamectl set-hostname <name>

(적용되려면 다시 로그인해야한다.)

그리고, 모든 대상 호스트들에서 터미널을 열어서 서로 위치를 알 수 있도록 프라이빗 ip와 대상 호스트이름을 아래와 같이 지정해주는 작업을 한다. (터미널에 여러 탭 동시 입력 기능이 있으면 좋다. hyper.js 의 경우 hyper-broadcast를 사용하면 가능하다.)

스크린샷 2021-07-30 오후 5 50 26

운영체제 레벨 시스템 설정 (containerd 활성화)

우분투 기준 k8s를 설치하기 위해 상당히 복잡한 시스템 설정을 하는데, 정확히 뭘 하는지 잘 모르겠다.

다음 설정들을 모든 호스트에서 건드린다.

/etc/modules-load.d/containerd.conf
설정 수정후 modprobe로 재시작

/etc/sysctl.d/99-kubernetes-cri.conf
sysctl로 재부팅 없이 적용

그 다음, apt로 containerd 패키지 설치,
systemctl로 재시작 후 status 확인

다행히 sudo systemctl status containerd로 확인한 결과 아래와 같이 실행중이므로 스킵해도 될 듯하다.

스크린샷 2021-07-30 오후 6 05 38

k8s 패키지 설치

  • sudo swapoff -a로 스왑 비활성화
  • etc/fstab 설정 수정하여 항상 스왑 비활성화하도록 적용
  • apt-transport-https 패키지 설치
  • k8s 저장소의 gpg key 등록
  • k8s 저장소를 apt 저장소리스트에 등록
  • apt update, kubelet, kubeadm, kubectl 설치
  • apt mark hold <packages...> 명령으로 자동 업데이트 되지 않도록 버전 고정 설정

클러스터 초기화

  • control 노드에서,
  • worker 노드에서
    • 위에서 카피한 명령으로 클러스터에 참가
    • 실행 노드 확인

스크린샷 2021-07-30 오후 6 26 06

k8s 네트워크는 아래 블로그에 굉장히 잘 정리되어 있다.

https://medium.com/finda-tech/kubernetes-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%A0%95%EB%A6%AC-fccd4fd0ae6

sport

cf 1555

A

15 6 -> 300 120 20 8 -> 300 120 25 10 -> 300 120

사실상 비율이 같으므로, 나머지를 최소로 하면 될 듯하다. 300을 넘어가는 값은 300으로 나눈것만 계산하면 된다.

300 이하의 값의 정답은 어떻게 계산하나? 0부터 올라가면서, 300까지가 시간이니, 각 시간 기준 이전 시간들 참조해서 업데이트하는 스위핑방식으로 업데이트하면 될 듯하다.

15 15 15 15 15 15 30 30 30 30 30 30 …

문제가.. lower_bound? 같은 느낌이라 조건을 어떻게 잡아야 하는지 헷갈린다. 120기준으로 나눠버리면 123 이런수는 제대로 고려가 안된다.. 즉 나누되, 남는 수가 일정 이상이 되어야 한다.

복잡하다. 그냥 대충 생각하면 120이상이면 2당 5가 증가하는데, 120 300 12 30 2 5 …

rust solution
fn solve<R: io::BufRead, W: io::Write>(scan: &mut UnsafeScanner<R>, out: &mut W) {
    let cases = ri32(scan);
    let mut arr= vec![15i64; 250];
    use std::cmp::min;
    for i in 0..245 {
        let idx = i as i64;
        let mut cur_min = i64::MAX;
        if idx-6 >= 0 {
            cur_min = min(cur_min, arr[i-6]+15);
        }
        if idx-8 >= 0 {
            cur_min = min(cur_min, arr[i-8]+20);
        }
        if idx-10 >= 0 {
            cur_min = min(cur_min, arr[i-10]+25);
        }
        if idx <= 6 {
            cur_min = 15;
        } else if idx <= 8 { // 이부분과 아래 케이스를 처리 안했어서 여러번 틀렸음..
            cur_min = 20;
        } else if idx <= 10 {
            cur_min = 25;
        }
        arr[i] = cur_min;
    }
    arr[0] = 0;

    // dbg!(&arr);

    for case in 0..cases {
        let n = ri64(scan);

        let div = n / 2;
        let left = n % 2;

        if n < 120 {
            writeln!(out, "{}", arr[n as usize]);
        } else {
            writeln!(out, "{}", div*5+left*5);
        }
    }
}

꼭 이런 마감 처리에서 시간을 많이 뺏긴다. 완벽하고 깔끔하게 맞는 조건으로 짜려면 어떻게 연습해야 하는 것일까? 완전 논리적 증명 후 풀이??..

B

이건 진짜 종이 없인 못풀듯. 그림 그려서 풀었다.

rust solution
fn solve<R: io::BufRead, W: io::Write>(scan: &mut UnsafeScanner<R>, out: &mut W) {
    let cases = ri32(scan);
    
    for _ in 0..cases {
        let (W,H) = (rf64(scan), rf64(scan));
        let (x1,y1,x2,y2) = (rf64(scan), rf64(scan), rf64(scan), rf64(scan));
        let (w,h) = (rf64(scan), rf64(scan));
        
        let large_x = f64::max(x1, W-x2);
        let large_y = f64::max(y1, H-y2);
        
        let mut overlap_w = f64::max(w-large_x, 0.0);
        let mut overlap_h = f64::max(h-large_y, 0.0);
        
        if w+(x2-x1) > W {
            overlap_w = f64::MAX;
        }
        if h+(y2-y1) > H {
            overlap_h = f64::MAX;
        }

        let min_dist = f64::min(overlap_w, overlap_h);
        if min_dist >= 100000005.0 {
            writeln!(out, "{}", -1);
        } else {
            writeln!(out, "{:.8}", min_dist);
        }
    }
}

C

A보다도 시간이 덜 걸린 것 같다. 아이디어 자체도 간단하고 구현도 간단하다. A에 시간을 너무 써서 대회 시간 내에 풀지 못했다.

rust solution

fn solve<R: io::BufRead, W: io::Write>(scan: &mut UnsafeScanner<R>, out: &mut W) {
    let cases = ri32(scan);
    
    for _ in 0..cases {
        let mut arr1 = vec![];
        let mut arr2 = vec![];
        let mut sums1 = vec![];
        let mut sums2 = vec![];
        let mut maxv1 = 0;
        let mut maxv2 = 0;

        let m = ri32(scan);
        
        for i in 0..m { 
            let val = ri32(scan);
            arr1.push(val);
            maxv1 += val;
        }
        for i in 0..m { 
            let val = ri32(scan);
            arr2.push(val);
            maxv2 += val;
        }

        let mut leftsums = maxv1;
        for (i, item1) in arr1.iter().enumerate() {
            let val = item1.clone();
            sums1.push(leftsums);
            leftsums -= val;
        }
        sums1.push(0);

        let mut lastsums = 0;
        for (i, item2) in arr2.iter().enumerate() {
            let val = item2.clone();
            sums2.push(lastsums);
            lastsums += val;
        }

        let mut min_so_far = i32::MAX;
        let mut cur_max = 0;

        for idx in 0..m {
            cur_max = i32::max(sums1[(idx + 1) as usize], sums2[(idx) as usize]);
            if cur_max < min_so_far {
                min_so_far = cur_max;
            }
        }

        // dbg!(sums1);
        // dbg!(sums2);

        writeln!(out, "{}", min_so_far);
    }
}

Comments