태그 보관물: deployment

deployment

소프트웨어 / 펌웨어 자동 업데이트 전략 소프트웨어 정보

“고객 데모를위한 조잡한 카페인 기반 프로토 타입”단계가 거의 끝 나가고 “미래에 대해 생각하기”단계로 전환되는 중형 프로젝트가 있습니다. 이 프로젝트는 소프트웨어 및 펌웨어가있는 Linux 기반 장치와 중앙 관리 웹 서버로 구성됩니다. 현재 10 개의 프로토 타입이 존재하며 1000 대 정도의 생산이 예상됩니다.

자동 업데이트 기술에 정통하지 않고 시간이 부족하기 때문에 소프트웨어 배포 / 자동 업데이트 전략을 신속하게 수행했으며 솔직히 말해서 짜증납니다. 현재 다음과 같이 구성되어 있습니다.

  • 프로덕션 릴리스 브랜치가있는 호스팅 된 git repo (GitLab) (웹 서버 소스도 이와 동일한 리포지토리 및 기타 다른 리포지토리에 있음)
  • 웹 인터페이스의 “배치 업데이트”버튼 :
    1. 프로덕션 릴리스 분기에서 최신 버전을 로컬 저장소 영역으로 가져 와서 임시 패키지 준비 준비 영역에 복사합니다.
    2. 준비 영역에서 레포에 저장된 살균 스크립트를 실행하여 관련없는 소스 파일 (예 : 서버 소스, 펌웨어 소스 등) 및 .git 파일을 제거합니다.
    3. 현재 git 해시를 업데이트 패키지의 파일에 씁니다 (아래에서 목적이 명확 해짐).
    4. 모두 잘 작동하면 gzip을 압축하고 이전 gzipped 패키지를 동일한 이름의 파일로 덮어 써서 서비스 할 준비를 한 다음 준비 영역을 삭제합니다.
    5. 서버에 현재 장치 소프트웨어의 사본 두 개가 동기화되어있을 것입니다. 최신 프로덕션 지점의 전체 로컬 git 저장소 및 이제 다음을 나타내는 것으로 가정 할 준비가 된 gzipped 패키지 같은 버전.
  • 장치의 소프트웨어는라는 디렉토리에 자체적으로 포함되어 있습니다.이 디렉토리 /opt/example/current는 현재 버전의 소프트웨어에 대한 심볼릭 링크입니다.
  • 부팅시 장치의 자동 업데이트 기능 :
    1. do_not_update파일 이 있는지 확인하고 존재하는 경우 추가 조치를 취하지 않습니다 (개발 장치의 경우 아래 참조).
    2. 위에서 언급 한 텍스트 파일에서 현재 커밋 해시를 읽습니다.
    3. 해시를 쿼리 매개 변수로 사용하여 서버에 HTTP 요청을 작성합니다. 서버는 304 (해시는 최신 버전)로 응답하거나 gzip으로 업데이트 된 패키지를 제공합니다.
    4. 업데이트 패키지를받은 경우 다음 위치에 설치합니다 /opt/example.
      1. 업데이트 된 소프트웨어 정보 추출 폴더 이름이 stage.
      2. 업데이트 패키지에서 설치 후 스크립트를 실행하여 해당 업데이트에 필요한 로컬 변경 등을 수행합니다.
      3. 현재 소프트웨어 루트 폴더를에 복사 previous(기존 파일이있는 previous경우 먼저 삭제 )
      4. stage폴더를에 복사 latest(기존 폴더가있는 latest경우 먼저 삭제 )
      5. 보장 current을 차례로 심볼릭 링크 latest.
      6. 장치 재부팅 (펌웨어 업데이트가있는 경우 재부팅시 적용됨)

새로 구성된 장치에 초기 배포 문제도 있습니다. 장치는 현재 SD 카드를 기반으로하며 (여기서는 자체 범위의 문제가 있음)이 프로세스는 다음과 같이 구성됩니다.

  1. 안정적인 이전 버전의 소프트웨어가있는 SD 이미지가 있습니다.
  2. 이 이미지에서 SD 카드가 생성됩니다.
  3. 처음 부팅 할 때 다양한 최초 장치 별 (일련 번호 기반) 초기화가 수행 된 다음 자동 업데이터가 평소대로 최신 프로덕션 버전의 소프트웨어를 설치합니다.

또한 개발 장치에 대한 지원이 필요했습니다. 개발 장치의 경우 :

  • 전체 로컬 자식 저장소는 장치에서 유지 관리됩니다.
  • current심볼릭 링크는 개발 디렉토리를 가리 킵니다.
  • do_not_update자동 업데이트 프로그램이 프로덕션 업데이트로 개발 코드를 날려 버리지 못하게 하는 로컬 파일이 있습니다.

이제 배포 프로세스는 이론적으로 다음과 같습니다.

  1. 코드를 배포 할 준비가되면 릴리스 지점으로 푸시하십시오.
  2. 서버에서 “deploy update”버튼을 누릅니다.
  3. 이제 업데이트가 적용되고 다음에 확인할 때 장치가 자동 업데이트됩니다.

그러나, 거기 연습 문제는 :

  • 웹 서버 코드는 장치 코드와 동일한 저장소에 있으며 서버에는 로컬 git 저장소가 있습니다. 최신 웹 서버 코드는 최신 장치 코드와 동일한 브랜치에 없습니다. 디렉토리 구조에 문제가 있습니다. “업로드 배치”단추가 프로덕션 분기에서 최신 버전을 가져 오면 서버 코드의 서브 디렉토리로 가져옵니다. 즉, 처음부터 서버에 배포 할 때 배포를 시도하지 않으면 장치 제작 분기를 가져 와서이 하위 디렉터리를 수동으로 “시드”해야합니다. 부모 디렉토리의 웹 서버 브랜치 에서 장치 코드를 가져옵니다 . 스테이징 영역을 서버의 로컬 git repo의 하위 디렉토리로 만들면 해결할 수 있다고 생각합니다.
  • 웹 서버는 현재 장치 소프트웨어의 git 해시를 지속적으로 유지하지 않습니다. 서버 시작시 git rev-parse HEAD로컬 장치 소프트웨어 저장소에서 현재 해시를 검색합니다. 내가 머리를 감쌀 수없는 이유 때문에 여기에서 설명하지 않는 수많은 논리 오류가 발생합니다. 특히 서버를 다시 시작하면 서버가 새롭고 생산이없는 경우 때로는 서버를 다시 시작하는 것으로 충분합니다. 브랜치 레포는 아직 뽑혔습니다. 요청이있는 경우 해당 논리의 소스를 기꺼이 공유하지만이 게시물이 오래 걸립니다.
  • 어떤 이유로 살균 스크립트 (서버 측)가 실패하면 서버에 최신 리포지토리가 있지만 동기화되지 않은 / 실패 업데이트 패키지가 남아 있으므로 git rev-parse HEAD실제로 존재하는 것과 일치하지 않는 해시를 반환합니다. 서버 명령 행에서 수동으로 수정해야합니다. 즉, 서버는 업데이트 패키지가 정확하지 않다는 것을 알지 못하며 항상 순수한 믿음으로 가정합니다. 이 점을 이전 지점과 결합하면 실제로 서버가 매우 취약합니다.
  • 가장 큰 문제 중 하나는 다음과 같습니다. 현재 장치에서 별도의 업데이터 데몬이 실행되고 있지 않습니다. Wi-Fi 인터넷 접속을 기다리는 합병증과 막판 해커로 인해 장치를 확인하고 업데이트하는 것은 주요 장치 제어 소프트웨어 자체입니다. 즉, 제대로 테스트되지 않은 버전으로 인해 프로덕션 환경으로 전환되고 제어 소프트웨어를 시작할 수없는 경우 더 이상 자체 업데이트 할 수 없으므로 존재하는 모든 장치가 기본적으로 차단됩니다. 이것은 생산에서 절대 악몽 일 것입니다. 운이 좋지 않은 시간에 전원이 꺼지면 단일 장치에 대해서도 마찬가지입니다.
  • 다른 주요 문제점은 다음과 같습니다 . 증분 업데이트가 지원되지 않습니다. 예를 들어 장치가 한동안 켜지지 않으면 다음에 업데이트 할 때 여러 릴리스 버전을 건너 뛰면 직접 버전 건너 뛰기 업데이트를 수행 할 수 있어야합니다. 이로 인해 배포가 업데이트되면 주어진 업데이트를 이전 버전 위에 적용 할 수있게하는 악몽이됩니다. 또한 git 해시는 버전 번호가 아닌 버전을 식별하는 데 사용되므로 증분 업데이트를 용이하게하기 위해 버전을 사 전적으로 비교할 수 없습니다.
  • 현재 지원하지 않는 새로운 요구 사항은 관리 서버 측에서 구성해야하는 일부 장치 별 구성 옵션 (키 / 값 쌍)이 존재해야한다는 것입니다. 소프트웨어 업데이트와 동일한 HTTP 요청 (어쩌면 HTTP 헤더 / 쿠키로 캡슐화 할 수 있음)로 장치 당 옵션을 장치에 다시 제공하는 것이 마음에 들지 않을 것입니다. 항상 별도의 HTTP 요청으로 만드십시오.
  • 하드웨어 버전이 두 개 이상 존재하기 때문에 약간의 합병증이 있습니다. 하드웨어의 현재 버전은 실제로 초기 SD 이미지에 환경 변수로 저장되며 (자체를 식별 할 수 없음) 모든 소프트웨어는 모든 버전의 장치와 호환되도록 설계되었습니다. 펌웨어 업데이트는이 환경 변수를 기반으로 선택되며 업데이트 패키지에는 모든 버전의 하드웨어에 대한 펌웨어가 포함됩니다. 조금 어색하지만 나는 이것으로 살 수 있습니다.
  • 현재 수동으로 장치에 업데이트를 업로드 할 수있는 방법이 없습니다 (오랫동안 말해서이 장치에는 두 개의 wifi 어댑터가 있습니다. 하나는 인터넷에 연결하고 다른 하나는 사용자가 장치를 구성하는 데 사용하는 AP 모드입니다. 장치의 로컬 웹 인터페이스에 “소프트웨어 업데이트”기능을 추가하려고합니다. 이것은 큰 문제는 아니지만 업데이트 설치 방법에 영향을 미칩니다.
  • 다른 좌절과 전반적인 불안감.

그래서 … 그것은 길었다. 그러나 내 질문은 이것으로 요약됩니다.

이 작업을 올 바르고 안전하게 수행하려면 어떻게해야합니까? 기존 프로세스를 약간 조정할 수 있습니까? 시간이 오래 걸리는 전략 / 기존 시스템이있어 자체 업데이트 시스템을 롤백 할 필요가 없습니까? 또는 내 자신의 롤을해야하는 경우 배포 / 업데이트 프로세스가 안전하고 성공하기 위해서는 무엇이 필요한가? 또한 믹스에 개발 장치를 포함시킬 수 있어야합니다.

질문이 명확하기를 바랍니다. 나는 그것이 약간 희미하다는 것을 알고 있지만, 이것이 전에 해결되어 성공적으로 해결 된 문제라는 것을 100 % 확신합니다. 현재 받아 들여진 전략이 무엇인지 모릅니다.



답변

사용중인 Linux 배포, 부트 로더 및 아키텍처 (x86, ARM, MIPS?)에 대한 자세한 정보를 제공 할 수 있습니까?

나는 어느 쪽이든 추측하고 당신을 올바른 방향으로 향하게 할 것입니다.

U-Boot의 Yocto 기반 배포판 인 경우 mender.io 또는 swupdate를 참조하십시오 . 이 프로젝트는 기준에 잘 맞는 것 같습니다. 그들의 주요 목표는 원자 업데이트를 보장하는 것입니다.

가장 큰 문제 중 하나는 다음과 같습니다. 현재 장치에서 별도의 업데이터 데몬이 실행되고 있지 않습니다. Wi-Fi 인터넷 접속을 기다리는 합병증과 마지막 순간의 해커로 인해 주요 장치 제어 소프트웨어 자체가 장치를 확인하고 업데이트합니다. 즉, 제대로 테스트되지 않은 버전으로 인해 프로덕션 환경으로 전환되고 제어 소프트웨어를 시작할 수없는 경우 더 이상 자체 업데이트 할 수 없으므로 존재하는 모든 장치가 기본적으로 차단됩니다. 이것은 생산에서 절대 악몽 일 것입니다. 운이 좋지 않은 시간에 전원이 꺼지면 단일 장치에 대해서도 마찬가지입니다.

Mender는 Go에서 작성된 데몬 (및 시스템화 된 스크립트)을 포함하여 이러한 부담을 덜어주는 다양한 도구를 제공합니다. 이 프로젝트는 Yocto와 함께 사용하기가 매우 쉽습니다 (특정 사례 및 파티션 레이아웃에 쉽게 적용 할 수있는 많은 장치에 메타 레이어를 제공합니다. 인기있는 SOC를위한 즉시 사용할 수있는 솔루션이 많이 있습니다) . Yocto를 사용하지 않는 경우이 게시물 을 살펴보면 비 Yocto 기반 배포판과 함께 사용하기 위해 수행해야하는 단계를 정확하게 설명 할 수 있습니다 .

swupdate도 꽤 훌륭하지만 DENX (U-Boot의 조직)의 한 사람의 노력으로 보입니다. 꽤 성숙한 것 같습니다.

경험이없는 Ubuntu Snappy도 있으며 이것에 대해 유능하게 의견을 말할 수 없습니다 (아마도 누군가 투쟁 할 것입니다). 아이디어는 독립형 “스냅”으로 앱을 제공하는 것입니다. 내가 이해 한 바에 따르면 이것은 시스템 전체가 아니기 때문에 문제에 대한 해결책은 거의 없습니다.

질문이 명확하기를 바랍니다. 나는 그것이 약간 희미하다는 것을 알고 있지만, 이것이 전에 해결되어 성공적으로 해결 된 문제라는 것을 100 % 확신합니다. 현재 받아 들여진 전략이 무엇인지 모릅니다.

실제로 오늘날 트렌드는 APT / YUM보다 Docker (내장 시스템에서도)와 친구를 사용하는 것 같습니다. 나중에 일관성을 유지하기가 매우 어려울 수 있습니다.


답변